[systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
From: Harald Hoyer har...@redhat.com If cryptsetup is called with a source device as argv[3], then craft the ID for the password agent with a unique device path. If possible /dev/block/maj:min is used, otherwise the original argv[3] is used. This enables password agents like petera [1] to provide a password according to the source device. The original ID did not carry enough information and was more targeted for a human readable string, which is specified in the Message field anyway. With this patch the ID of the ask.XXX ini file looks like this: ID=cryptsetup:/dev/block/maj:min [1] https://github.com/npmccallum/petera --- src/cryptsetup/cryptsetup.c | 97 ++--- 1 file changed, 66 insertions(+), 31 deletions(-) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index a5018f1..130c36e 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -238,6 +238,33 @@ static void log_glue(int level, const char *msg, void *usrptr) { log_debug(%s, msg); } +static char* disk_maj_min(const char *path) { +struct stat st, st2; +char *i = NULL; +int r; + +assert(path); + +if (stat(path, st) 0) +return NULL; + +if (!S_ISBLK(st.st_mode)) +return NULL; + +asprintf(i, /dev/block/%d:%d, major(st.st_rdev), minor(st.st_rdev)); + +if (!i) +return strdup(path); + +r = stat(i, st2); +if ((r 0) || (st.st_rdev != st2.st_rdev)) { +free(i); +return strdup(path); +} + +return i; +} + static char* disk_description(const char *path) { static const char name_fields[] = @@ -295,20 +322,54 @@ static char *disk_mount_point(const char *label) { return NULL; } -static int get_password(const char *name, usec_t until, bool accept_cached, char ***passwords) { -int r; +static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***passwords) { +int r = 0; char **p; _cleanup_free_ char *text = NULL; _cleanup_free_ char *escaped_name = NULL; char *id; +const char *name = NULL; +_cleanup_free_ char *description = NULL, *name_buffer = NULL, +*mount_point = NULL, *maj_min = NULL; assert(name); assert(passwords); +description = disk_description(src); +mount_point = disk_mount_point(vol); + +if (description streq(vol, description)) { +/* If the description string is simply the + * volume name, then let's not show this + * twice */ +free(description); +description = NULL; +} + +if (mount_point description) +r = asprintf(name_buffer, %s (%s) on %s, description, vol, mount_point); +else if (mount_point) +r = asprintf(name_buffer, %s on %s, vol, mount_point); +else if (description) +r = asprintf(name_buffer, %s (%s), description, vol); + +if (r 0) { +log_oom(); +return r; +} +name = name_buffer ? name_buffer : vol; + if (asprintf(text, Please enter passphrase for disk %s!, name) 0) return log_oom(); -escaped_name = cescape(name); +if (src) +maj_min = disk_maj_min(src); + +if (maj_min) +escaped_name = maj_min; +else +escaped_name = cescape(name); + if (!escaped_name) return log_oom(); @@ -552,8 +613,7 @@ int main(int argc, char *argv[]) { unsigned tries; usec_t until; crypt_status_info status; -const char *key_file = NULL, *name = NULL; -_cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL; +const char *key_file; /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */ @@ -581,31 +641,6 @@ int main(int argc, char *argv[]) { /* A delicious drop of snake oil */ mlockall(MCL_FUTURE); -description = disk_description(argv[3]); -mount_point = disk_mount_point(argv[2]); - -if (description streq(argv[2], description)) { -/* If the description string is simply the - * volume name, then let's not show this - * twice */ -free(description); -description = NULL; -} - -k = 0; -if (mount_point description) -k = asprintf(name_buffer, %s (%s) on %s, description, argv[2], mount_point); -else if
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
Patchset imported to github. Pull request: https://github.com/systemd-devs/systemd/compare/master...systemd-mailing-devs:1432894632-2417-1-git-send-email-harald%40redhat.com -- Generated by https://github.com/haraldh/mail2git ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
On Fri, 29.05.15 12:17, har...@redhat.com (har...@redhat.com) wrote: +static char* disk_maj_min(const char *path) { I'd really not abbreivate things here... call it major and minor. there's no point in saving two ors... +struct stat st, st2; +char *i = NULL; +int r; + +assert(path); + +if (stat(path, st) 0) +return NULL; + +if (!S_ISBLK(st.st_mode)) +return NULL; + +asprintf(i, /dev/block/%d:%d, major(st.st_rdev), minor(st.st_rdev)); + +if (!i) +return strdup(path); I'd really prefer if we would propagate errors properly here. I.e. change the function to: static int disk_major_minor(const char *path, char **ret); Then, return proper error codes, and the newly allocated name in *ret. + +r = stat(i, st2); +if ((r 0) || (st.st_rdev != st2.st_rdev)) { +free(i); +return strdup(path); +} Why the second stat() check? I think we can be reasonably sure that these device nodes will use the right major/minor... (Also, the extra () seem unnecessary...) Otherwise looks fine. Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
On Fri, 29.05.15 15:45, Dimitri John Ledkov (dimitri.j.led...@intel.com) wrote: On 29 May 2015 at 11:17, har...@redhat.com wrote: From: Harald Hoyer har...@redhat.com If cryptsetup is called with a source device as argv[3], then craft the ID for the password agent with a unique device path. I'm not sure why this is needed... if the device path is not good enough, there is also luks UUID header. In Ubuntu we display the full cryptsetup UUID in plymouth, but that's fairly cosmetic. If the path is not good enough, maj/min are a bit pointless and you really probably want the luks UUID then. Harald actually convinced me now that this is useful indeed, simply to ensure that if multiple invocations of systemd-cryptsetup using different device aliases actually result in the same id used in the password file. Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
Harald Hoyer [2015-05-29 16:50 +0200]: I was more thinking about symlinks pointing to the same device. Naïvely I'd think that resolving symlinks would still be more readable than major/minor numbers; why would that be worse? Thanks, Martin -- Martin Pitt| http://www.piware.de Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org) ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
On Fri, 29.05.15 17:01, Martin Pitt (martin.p...@ubuntu.com) wrote: Harald Hoyer [2015-05-29 16:50 +0200]: I was more thinking about symlinks pointing to the same device. Naïvely I'd think that resolving symlinks would still be more readable than major/minor numbers; why would that be worse? Well, sure, one can do that too. However, internally in udev we generally identify devices by the major/minor or by their network interface index, since these are not subject to renames ever... And I think this tool should follow what we do in udev in this regard, I guess. Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
Am 29.05.2015 um 17:04 schrieb Lennart Poettering: On Fri, 29.05.15 12:17, har...@redhat.com (har...@redhat.com) wrote: +static char* disk_maj_min(const char *path) { I'd really not abbreivate things here... call it major and minor. there's no point in saving two ors... +struct stat st, st2; +char *i = NULL; +int r; + +assert(path); + +if (stat(path, st) 0) +return NULL; + +if (!S_ISBLK(st.st_mode)) +return NULL; + +asprintf(i, /dev/block/%d:%d, major(st.st_rdev), minor(st.st_rdev)); + +if (!i) +return strdup(path); I'd really prefer if we would propagate errors properly here. I.e. change the function to: static int disk_major_minor(const char *path, char **ret); ret as the last or the first argument? Then, return proper error codes, and the newly allocated name in *ret. just copied the scheme of disk_description() and disk_mount_point() :-) + +r = stat(i, st2); +if ((r 0) || (st.st_rdev != st2.st_rdev)) { +free(i); +return strdup(path); +} Why the second stat() check? I think we can be reasonably sure that these device nodes will use the right major/minor... Yes, what if it is missing? Someone removed it or played games :) Sure, can remove the rdev check. (Also, the extra () seem unnecessary...) Otherwise looks fine. Lennart ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
On 29 May 2015 at 11:17, har...@redhat.com wrote: From: Harald Hoyer har...@redhat.com If cryptsetup is called with a source device as argv[3], then craft the ID for the password agent with a unique device path. I'm not sure why this is needed... if the device path is not good enough, there is also luks UUID header. In Ubuntu we display the full cryptsetup UUID in plymouth, but that's fairly cosmetic. If the path is not good enough, maj/min are a bit pointless and you really probably want the luks UUID then. Regards, Dimitri. If possible /dev/block/maj:min is used, otherwise the original argv[3] is used. This enables password agents like petera [1] to provide a password according to the source device. The original ID did not carry enough information and was more targeted for a human readable string, which is specified in the Message field anyway. With this patch the ID of the ask.XXX ini file looks like this: ID=cryptsetup:/dev/block/maj:min [1] https://github.com/npmccallum/petera --- src/cryptsetup/cryptsetup.c | 97 ++--- 1 file changed, 66 insertions(+), 31 deletions(-) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index a5018f1..130c36e 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -238,6 +238,33 @@ static void log_glue(int level, const char *msg, void *usrptr) { log_debug(%s, msg); } +static char* disk_maj_min(const char *path) { +struct stat st, st2; +char *i = NULL; +int r; + +assert(path); + +if (stat(path, st) 0) +return NULL; + +if (!S_ISBLK(st.st_mode)) +return NULL; + +asprintf(i, /dev/block/%d:%d, major(st.st_rdev), minor(st.st_rdev)); + +if (!i) +return strdup(path); + +r = stat(i, st2); +if ((r 0) || (st.st_rdev != st2.st_rdev)) { +free(i); +return strdup(path); +} + +return i; +} + static char* disk_description(const char *path) { static const char name_fields[] = @@ -295,20 +322,54 @@ static char *disk_mount_point(const char *label) { return NULL; } -static int get_password(const char *name, usec_t until, bool accept_cached, char ***passwords) { -int r; +static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***passwords) { +int r = 0; char **p; _cleanup_free_ char *text = NULL; _cleanup_free_ char *escaped_name = NULL; char *id; +const char *name = NULL; +_cleanup_free_ char *description = NULL, *name_buffer = NULL, +*mount_point = NULL, *maj_min = NULL; assert(name); assert(passwords); +description = disk_description(src); +mount_point = disk_mount_point(vol); + +if (description streq(vol, description)) { +/* If the description string is simply the + * volume name, then let's not show this + * twice */ +free(description); +description = NULL; +} + +if (mount_point description) +r = asprintf(name_buffer, %s (%s) on %s, description, vol, mount_point); +else if (mount_point) +r = asprintf(name_buffer, %s on %s, vol, mount_point); +else if (description) +r = asprintf(name_buffer, %s (%s), description, vol); + +if (r 0) { +log_oom(); +return r; +} +name = name_buffer ? name_buffer : vol; + if (asprintf(text, Please enter passphrase for disk %s!, name) 0) return log_oom(); -escaped_name = cescape(name); +if (src) +maj_min = disk_maj_min(src); + +if (maj_min) +escaped_name = maj_min; +else +escaped_name = cescape(name); + if (!escaped_name) return log_oom(); @@ -552,8 +613,7 @@ int main(int argc, char *argv[]) { unsigned tries; usec_t until; crypt_status_info status; -const char *key_file = NULL, *name = NULL; -_cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL; +const char *key_file; /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */ @@ -581,31 +641,6 @@ int main(int argc, char *argv[]) { /* A delicious drop of snake oil */ mlockall(MCL_FUTURE); -description = disk_description(argv[3]); -mount_point = disk_mount_point(argv[2]); - -if (description streq(argv[2],
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
Am 29.05.2015 um 16:38 schrieb Lennart Poettering: On Fri, 29.05.15 16:30, Harald Hoyer (har...@redhat.com) wrote: Am 29.05.2015 um 16:26 schrieb Lennart Poettering: On Fri, 29.05.15 12:17, har...@redhat.com (har...@redhat.com) wrote: From: Harald Hoyer har...@redhat.com If cryptsetup is called with a source device as argv[3], then craft the ID for the password agent with a unique device path. If possible /dev/block/maj:min is used, otherwise the original argv[3] is used. Why use the major/minor numebrs here? Why isn't the original device name good enough? Don't we want a kind of unique ID? But the original device path is already unique? I mean, it's a path in the file heirarchy, that already makes it unique. Or what do you mean by unique? Lennart I was more thinking about symlinks pointing to the same device. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
On Fri, 29.05.15 16:30, Harald Hoyer (har...@redhat.com) wrote: Am 29.05.2015 um 16:26 schrieb Lennart Poettering: On Fri, 29.05.15 12:17, har...@redhat.com (har...@redhat.com) wrote: From: Harald Hoyer har...@redhat.com If cryptsetup is called with a source device as argv[3], then craft the ID for the password agent with a unique device path. If possible /dev/block/maj:min is used, otherwise the original argv[3] is used. Why use the major/minor numebrs here? Why isn't the original device name good enough? Don't we want a kind of unique ID? But the original device path is already unique? I mean, it's a path in the file heirarchy, that already makes it unique. Or what do you mean by unique? Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
Am 29.05.2015 um 16:45 schrieb Dimitri John Ledkov: On 29 May 2015 at 11:17, har...@redhat.com wrote: From: Harald Hoyer har...@redhat.com If cryptsetup is called with a source device as argv[3], then craft the ID for the password agent with a unique device path. I'm not sure why this is needed... if the device path is not good enough, there is also luks UUID header. In Ubuntu we display the full cryptsetup UUID in plymouth, but that's fairly cosmetic. If the path is not good enough, maj/min are a bit pointless and you really probably want the luks UUID then. Regards, Dimitri. This is the ID=... in the ask-xxx.ini file... The Message field, which is displayed to the user already contains a verbose description including the luks uuid. If possible /dev/block/maj:min is used, otherwise the original argv[3] is used. This enables password agents like petera [1] to provide a password according to the source device. The original ID did not carry enough information and was more targeted for a human readable string, which is specified in the Message field anyway. With this patch the ID of the ask.XXX ini file looks like this: ID=cryptsetup:/dev/block/maj:min [1] https://github.com/npmccallum/petera --- src/cryptsetup/cryptsetup.c | 97 ++--- 1 file changed, 66 insertions(+), 31 deletions(-) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index a5018f1..130c36e 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -238,6 +238,33 @@ static void log_glue(int level, const char *msg, void *usrptr) { log_debug(%s, msg); } +static char* disk_maj_min(const char *path) { +struct stat st, st2; +char *i = NULL; +int r; + +assert(path); + +if (stat(path, st) 0) +return NULL; + +if (!S_ISBLK(st.st_mode)) +return NULL; + +asprintf(i, /dev/block/%d:%d, major(st.st_rdev), minor(st.st_rdev)); + +if (!i) +return strdup(path); + +r = stat(i, st2); +if ((r 0) || (st.st_rdev != st2.st_rdev)) { +free(i); +return strdup(path); +} + +return i; +} + static char* disk_description(const char *path) { static const char name_fields[] = @@ -295,20 +322,54 @@ static char *disk_mount_point(const char *label) { return NULL; } -static int get_password(const char *name, usec_t until, bool accept_cached, char ***passwords) { -int r; +static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***passwords) { +int r = 0; char **p; _cleanup_free_ char *text = NULL; _cleanup_free_ char *escaped_name = NULL; char *id; +const char *name = NULL; +_cleanup_free_ char *description = NULL, *name_buffer = NULL, +*mount_point = NULL, *maj_min = NULL; assert(name); assert(passwords); +description = disk_description(src); +mount_point = disk_mount_point(vol); + +if (description streq(vol, description)) { +/* If the description string is simply the + * volume name, then let's not show this + * twice */ +free(description); +description = NULL; +} + +if (mount_point description) +r = asprintf(name_buffer, %s (%s) on %s, description, vol, mount_point); +else if (mount_point) +r = asprintf(name_buffer, %s on %s, vol, mount_point); +else if (description) +r = asprintf(name_buffer, %s (%s), description, vol); + +if (r 0) { +log_oom(); +return r; +} +name = name_buffer ? name_buffer : vol; + if (asprintf(text, Please enter passphrase for disk %s!, name) 0) return log_oom(); -escaped_name = cescape(name); +if (src) +maj_min = disk_maj_min(src); + +if (maj_min) +escaped_name = maj_min; +else +escaped_name = cescape(name); + if (!escaped_name) return log_oom(); @@ -552,8 +613,7 @@ int main(int argc, char *argv[]) { unsigned tries; usec_t until; crypt_status_info status; -const char *key_file = NULL, *name = NULL; -_cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL; +const char *key_file; /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */ @@ -581,31 +641,6 @@ int main(int argc, char *argv[]) { /* A delicious drop of
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
On Fri, 29.05.15 17:11, Harald Hoyer (har...@redhat.com) wrote: Am 29.05.2015 um 17:04 schrieb Lennart Poettering: On Fri, 29.05.15 12:17, har...@redhat.com (har...@redhat.com) wrote: +static char* disk_maj_min(const char *path) { I'd really not abbreivate things here... call it major and minor. there's no point in saving two ors... +struct stat st, st2; +char *i = NULL; +int r; + +assert(path); + +if (stat(path, st) 0) +return NULL; + +if (!S_ISBLK(st.st_mode)) +return NULL; + +asprintf(i, /dev/block/%d:%d, major(st.st_rdev), minor(st.st_rdev)); + +if (!i) +return strdup(path); I'd really prefer if we would propagate errors properly here. I.e. change the function to: static int disk_major_minor(const char *path, char **ret); ret as the last or the first argument? Usually we put that last. (except for object constructors, where we put it first since object methods always get their object specified as first arg...) Then, return proper error codes, and the newly allocated name in *ret. just copied the scheme of disk_description() and disk_mount_point() :-) Yeah, I guess that code is just old... + +r = stat(i, st2); +if ((r 0) || (st.st_rdev != st2.st_rdev)) { +free(i); +return strdup(path); +} Why the second stat() check? I think we can be reasonably sure that these device nodes will use the right major/minor... Yes, what if it is missing? Someone removed it or played games :) Sure, can remove the rdev check. Well, I#d prefer to avoid additional stat()s unless we have a really strong reason to have them in place. Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
On Fri, 29.05.15 12:17, har...@redhat.com (har...@redhat.com) wrote: From: Harald Hoyer har...@redhat.com If cryptsetup is called with a source device as argv[3], then craft the ID for the password agent with a unique device path. If possible /dev/block/maj:min is used, otherwise the original argv[3] is used. Why use the major/minor numebrs here? Why isn't the original device name good enough? Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup: craft a unique ID with the source device
Am 29.05.2015 um 16:26 schrieb Lennart Poettering: On Fri, 29.05.15 12:17, har...@redhat.com (har...@redhat.com) wrote: From: Harald Hoyer har...@redhat.com If cryptsetup is called with a source device as argv[3], then craft the ID for the password agent with a unique device path. If possible /dev/block/maj:min is used, otherwise the original argv[3] is used. Why use the major/minor numebrs here? Why isn't the original device name good enough? Lennart Don't we want a kind of unique ID? ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel