* [PATCH] genhomedircon: cleanup parsing of uid config values
@ 2025-10-21 11:36 Rahul Sandhu
2025-10-21 13:15 ` Stephen Smalley
0 siblings, 1 reply; 10+ messages in thread
From: Rahul Sandhu @ 2025-10-21 11:36 UTC (permalink / raw)
To: selinux; +Cc: Rahul Sandhu
Parsing KV files with a separator of similar format is fairly similar,
so we may as well add a helper function to make it easier to read.
Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
---
libsemanage/src/genhomedircon.c | 81 +++++++++++++--------------------
1 file changed, 32 insertions(+), 49 deletions(-)
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index 34056562..08a22df1 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -308,6 +308,29 @@ done:
return retval;
}
+static int parse_uid_config(const char *file, const char *key, const char *sep,
+ uid_t fallback, uid_t *out)
+{
+ char *path = semanage_findval(file, key, sep);
+ if (!path || !*path) {
+ free(path);
+ *out = fallback;
+ return 0;
+ }
+
+ char *endptr;
+ const unsigned long val = strtoul(path, &endptr, 0);
+ free(path);
+
+ if (endptr != path && *endptr == '\0') {
+ *out = (uid_t)val;
+ return 0;
+ }
+
+ *out = fallback;
+ return -1;
+}
+
static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
{
semanage_list_t *homedir_list = NULL;
@@ -315,7 +338,6 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
fc_match_handle_t hand;
char *path = NULL;
uid_t temp, minuid = 500, maxuid = 60000;
- int minuid_set = 0;
struct passwd *pwbuf;
struct stat buf;
@@ -362,56 +384,17 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
"Conversion failed for key " key ", is its value a number?" \
" Falling back to default value of `%s`.", #val);
- path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- minuid = (uid_t)val;
- minuid_set = 1;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
- minuid = FALLBACK_MINUID;
- minuid_set = 1;
- }
- }
- free(path);
- path = NULL;
+ if (parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid) < 0)
+ genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
- path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- maxuid = (uid_t)val;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
- maxuid = FALLBACK_MAXUID;
- }
- }
- free(path);
- path = NULL;
+ if (parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid) < 0)
+ genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
- path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- temp = (uid_t)val;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
- temp = FALLBACK_LU_UIDNUMBER;
- }
- if (!minuid_set || temp < minuid) {
- minuid = temp;
- minuid_set = 1;
- }
- }
- free(path);
- path = NULL;
+ if (parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp) < 0)
+ genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
+
+ if (temp < minuid)
+ minuid = temp;
#undef genhomedircon_warn_conv_fail
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] genhomedircon: cleanup parsing of uid config values
2025-10-21 11:36 [PATCH] genhomedircon: cleanup parsing of uid config values Rahul Sandhu
@ 2025-10-21 13:15 ` Stephen Smalley
2025-10-22 0:01 ` [PATCH v2] " Rahul Sandhu
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Smalley @ 2025-10-21 13:15 UTC (permalink / raw)
To: Rahul Sandhu; +Cc: selinux
On Tue, Oct 21, 2025 at 7:36 AM Rahul Sandhu <nvraxn@gmail.com> wrote:
>
> Parsing KV files with a separator of similar format is fairly similar,
> so we may as well add a helper function to make it easier to read.
>
> Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
> ---
> libsemanage/src/genhomedircon.c | 81 +++++++++++++--------------------
> 1 file changed, 32 insertions(+), 49 deletions(-)
>
> diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
> index 34056562..08a22df1 100644
> --- a/libsemanage/src/genhomedircon.c
> +++ b/libsemanage/src/genhomedircon.c
> @@ -308,6 +308,29 @@ done:
> return retval;
> }
>
> +static int parse_uid_config(const char *file, const char *key, const char *sep,
> + uid_t fallback, uid_t *out)
> +{
> + char *path = semanage_findval(file, key, sep);
Not new to this patch, but more obvious now that it is in a dedicated
helper: seems odd to call this path when it is a UID string.
> + if (!path || !*path) {
> + free(path);
> + *out = fallback;
> + return 0;
> + }
> +
> + char *endptr;
> + const unsigned long val = strtoul(path, &endptr, 0);
> + free(path);
> +
> + if (endptr != path && *endptr == '\0') {
This could end up dereferencing the memory you freed above.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2] genhomedircon: cleanup parsing of uid config values
2025-10-21 13:15 ` Stephen Smalley
@ 2025-10-22 0:01 ` Rahul Sandhu
2025-10-22 14:51 ` Stephen Smalley
0 siblings, 1 reply; 10+ messages in thread
From: Rahul Sandhu @ 2025-10-22 0:01 UTC (permalink / raw)
To: stephen.smalley.work; +Cc: nvraxn, selinux
Parsing KV files with a separator of similar format is fairly similar,
so we may as well add a helper function to make it easier to read.
Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
---
libsemanage/src/genhomedircon.c | 82 +++++++++++++--------------------
1 file changed, 33 insertions(+), 49 deletions(-)
v2: rename path to something more sensible (afterall, we are parsing a
UID!) and move the free to later, just before both return paths to
not dereference it when checking whether we actually parsed a valid
number or not.
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index 34056562..bb840856 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -308,6 +308,30 @@ done:
return retval;
}
+static int parse_uid_config(const char *file, const char *key, const char *sep,
+ uid_t fallback, uid_t *out)
+{
+ char *uid_str = semanage_findval(file, key, sep);
+ if (!uid_str || !*uid_str) {
+ free(uid_str);
+ *out = fallback;
+ return 0;
+ }
+
+ char *endptr;
+ const unsigned long val = strtoul(uid_str, &endptr, 0);
+
+ if (endptr != uid_str && *endptr == '\0') {
+ *out = (uid_t)val;
+ free(uid_str);
+ return 0;
+ }
+
+ free(uid_str);
+ *out = fallback;
+ return -1;
+}
+
static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
{
semanage_list_t *homedir_list = NULL;
@@ -315,7 +339,6 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
fc_match_handle_t hand;
char *path = NULL;
uid_t temp, minuid = 500, maxuid = 60000;
- int minuid_set = 0;
struct passwd *pwbuf;
struct stat buf;
@@ -362,56 +385,17 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
"Conversion failed for key " key ", is its value a number?" \
" Falling back to default value of `%s`.", #val);
- path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- minuid = (uid_t)val;
- minuid_set = 1;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
- minuid = FALLBACK_MINUID;
- minuid_set = 1;
- }
- }
- free(path);
- path = NULL;
+ if (parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid) < 0)
+ genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
- path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- maxuid = (uid_t)val;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
- maxuid = FALLBACK_MAXUID;
- }
- }
- free(path);
- path = NULL;
+ if (parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid) < 0)
+ genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
- path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- temp = (uid_t)val;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
- temp = FALLBACK_LU_UIDNUMBER;
- }
- if (!minuid_set || temp < minuid) {
- minuid = temp;
- minuid_set = 1;
- }
- }
- free(path);
- path = NULL;
+ if (parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp) < 0)
+ genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
+
+ if (temp < minuid)
+ minuid = temp;
#undef genhomedircon_warn_conv_fail
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2] genhomedircon: cleanup parsing of uid config values
2025-10-22 0:01 ` [PATCH v2] " Rahul Sandhu
@ 2025-10-22 14:51 ` Stephen Smalley
2025-10-24 8:07 ` [PATCH v3] " Rahul Sandhu
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Smalley @ 2025-10-22 14:51 UTC (permalink / raw)
To: Rahul Sandhu; +Cc: selinux
On Tue, Oct 21, 2025 at 8:01 PM Rahul Sandhu <nvraxn@gmail.com> wrote:
>
> Parsing KV files with a separator of similar format is fairly similar,
> so we may as well add a helper function to make it easier to read.
>
> Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
> ---
> libsemanage/src/genhomedircon.c | 82 +++++++++++++--------------------
> 1 file changed, 33 insertions(+), 49 deletions(-)
>
> v2: rename path to something more sensible (afterall, we are parsing a
> UID!) and move the free to later, just before both return paths to
> not dereference it when checking whether we actually parsed a valid
> number or not.
>
> diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
> index 34056562..bb840856 100644
> --- a/libsemanage/src/genhomedircon.c
> +++ b/libsemanage/src/genhomedircon.c
> @@ -315,7 +339,6 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> fc_match_handle_t hand;
> char *path = NULL;
> uid_t temp, minuid = 500, maxuid = 60000;
Should we be using our FALLBACK_* definitions above to initialize? Or
alternatively, do we need to initialize them at all since
parse_uid_config() always sets them?
> - int minuid_set = 0;
Not sure you can drop this altogether, see below.
> @@ -362,56 +385,17 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> "Conversion failed for key " key ", is its value a number?" \
> " Falling back to default value of `%s`.", #val);
>
> - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - minuid = (uid_t)val;
> - minuid_set = 1;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
> - minuid = FALLBACK_MINUID;
> - minuid_set = 1;
> - }
> - }
Note that minuid_set is NOT set to 1 if !path or !*path i.e. no
UID_MIN definition found at all in login.defs.
> - path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - temp = (uid_t)val;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> - temp = FALLBACK_LU_UIDNUMBER;
> - }
> - if (!minuid_set || temp < minuid) {
> - minuid = temp;
> - minuid_set = 1;
> - }
> - }
> - free(path);
> - path = NULL;
> + if (parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp) < 0)
> + genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> +
> + if (temp < minuid)
> + minuid = temp;
This might lower minuid to FALLBACK_LU_UIDNUMBER (500) even if it was
explicitly set by login.defs.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3] genhomedircon: cleanup parsing of uid config values
2025-10-22 14:51 ` Stephen Smalley
@ 2025-10-24 8:07 ` Rahul Sandhu
2025-10-24 19:29 ` Stephen Smalley
0 siblings, 1 reply; 10+ messages in thread
From: Rahul Sandhu @ 2025-10-24 8:07 UTC (permalink / raw)
To: stephen.smalley.work; +Cc: nvraxn, selinux
Parsing KV files with a separator of similar format is fairly similar,
so we may as well add a helper function to make it easier to read.
Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
---
libsemanage/src/genhomedircon.c | 107 +++++++++++++++++---------------
1 file changed, 57 insertions(+), 50 deletions(-)
v2: rename path to something more sensible (afterall, we are parsing a
UID!) and move the free to later, just before both return paths to
not dereference it when checking whether we actually parsed a valid
number or not.
v3: handle the fallback case for minuid properly such that we don't end
up always using a fallback if minuid is not set in login.defs, and
return a bool instead as it's a bit more sensible for what we're
trying to return. Also, check for ERANGE.
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index 34056562..e91c64e6 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -308,14 +308,52 @@ done:
return retval;
}
+/*
+ * Parses `file` for `key` seperated by `sep` into `out`.
+ * Returns:
+ * true on success.
+ * false on failure.
+ * `out` is guaranteed to be initalised.
+ * `fallback_set` is initalised to false, and set to true if a fallback was used.
+ */
+static bool parse_uid_config(const char *file, const char *key, const char *sep,
+ uid_t fallback, uid_t *out, bool *fallback_set)
+{
+ assert(out);
+ assert(fallback_set);
+
+ *fallback_set = false;
+
+ char *uid_str = semanage_findval(file, key, sep);
+ if (!uid_str || !*uid_str) {
+ free(uid_str);
+ *fallback_set = true;
+ *out = fallback;
+ return true;
+ }
+
+ char *endptr;
+ errno = 0;
+ const unsigned long val = strtoul(uid_str, &endptr, 0);
+
+ if (endptr != uid_str && *endptr == '\0' && errno != ERANGE) {
+ *out = (uid_t)val;
+ free(uid_str);
+ return true;
+ }
+
+ free(uid_str);
+ *fallback_set = true;
+ *out = fallback;
+ return false;
+}
+
static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
{
semanage_list_t *homedir_list = NULL;
semanage_list_t *shells = NULL;
fc_match_handle_t hand;
char *path = NULL;
- uid_t temp, minuid = 500, maxuid = 60000;
- int minuid_set = 0;
struct passwd *pwbuf;
struct stat buf;
@@ -362,56 +400,25 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
"Conversion failed for key " key ", is its value a number?" \
" Falling back to default value of `%s`.", #val);
- path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- minuid = (uid_t)val;
- minuid_set = 1;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
- minuid = FALLBACK_MINUID;
- minuid_set = 1;
- }
- }
- free(path);
- path = NULL;
+ uid_t minuid;
+ bool fallback_set;
+ if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid, &fallback_set))
+ genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
- path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- maxuid = (uid_t)val;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
- maxuid = FALLBACK_MAXUID;
- }
- }
- free(path);
- path = NULL;
+ const bool logindefs_minuid_fallback_set = fallback_set;
- path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- temp = (uid_t)val;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
- temp = FALLBACK_LU_UIDNUMBER;
- }
- if (!minuid_set || temp < minuid) {
- minuid = temp;
- minuid_set = 1;
- }
- }
- free(path);
- path = NULL;
+ uid_t temp;
+ if (!parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp, &fallback_set))
+ genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
+
+ if (logindefs_minuid_fallback_set)
+ minuid = temp;
+
+ uid_t maxuid;
+ /* We don't actually check fallback_set here, PATH_ETC_LOGIN_DEFS is the one source of
+ truth for UID_MAX. */
+ if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid, &fallback_set))
+ genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
#undef genhomedircon_warn_conv_fail
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3] genhomedircon: cleanup parsing of uid config values
2025-10-24 8:07 ` [PATCH v3] " Rahul Sandhu
@ 2025-10-24 19:29 ` Stephen Smalley
2025-10-26 19:13 ` [PATCH v4] " Rahul Sandhu
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Smalley @ 2025-10-24 19:29 UTC (permalink / raw)
To: Rahul Sandhu; +Cc: selinux
On Fri, Oct 24, 2025 at 4:08 AM Rahul Sandhu <nvraxn@gmail.com> wrote:
>
> Parsing KV files with a separator of similar format is fairly similar,
> so we may as well add a helper function to make it easier to read.
>
> Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> ---
> libsemanage/src/genhomedircon.c | 107 +++++++++++++++++---------------
> 1 file changed, 57 insertions(+), 50 deletions(-)
>
> v2: rename path to something more sensible (afterall, we are parsing a
> UID!) and move the free to later, just before both return paths to
> not dereference it when checking whether we actually parsed a valid
> number or not.
> v3: handle the fallback case for minuid properly such that we don't end
> up always using a fallback if minuid is not set in login.defs, and
> return a bool instead as it's a bit more sensible for what we're
> trying to return. Also, check for ERANGE.
>
> diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
> index 34056562..e91c64e6 100644
> --- a/libsemanage/src/genhomedircon.c
> +++ b/libsemanage/src/genhomedircon.c
> @@ -308,14 +308,52 @@ done:
> return retval;
> }
>
> +/*
> + * Parses `file` for `key` seperated by `sep` into `out`.
> + * Returns:
> + * true on success.
> + * false on failure.
> + * `out` is guaranteed to be initalised.
> + * `fallback_set` is initalised to false, and set to true if a fallback was used.
> + */
> +static bool parse_uid_config(const char *file, const char *key, const char *sep,
> + uid_t fallback, uid_t *out, bool *fallback_set)
> +{
> + assert(out);
> + assert(fallback_set);
> +
> + *fallback_set = false;
> +
> + char *uid_str = semanage_findval(file, key, sep);
> + if (!uid_str || !*uid_str) {
> + free(uid_str);
> + *fallback_set = true;
> + *out = fallback;
> + return true;
> + }
> +
> + char *endptr;
> + errno = 0;
> + const unsigned long val = strtoul(uid_str, &endptr, 0);
> +
> + if (endptr != uid_str && *endptr == '\0' && errno != ERANGE) {
> + *out = (uid_t)val;
> + free(uid_str);
> + return true;
> + }
> +
> + free(uid_str);
> + *fallback_set = true;
> + *out = fallback;
> + return false;
> +}
> +
> static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> {
> semanage_list_t *homedir_list = NULL;
> semanage_list_t *shells = NULL;
> fc_match_handle_t hand;
> char *path = NULL;
> - uid_t temp, minuid = 500, maxuid = 60000;
> - int minuid_set = 0;
> struct passwd *pwbuf;
> struct stat buf;
>
> @@ -362,56 +400,25 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> "Conversion failed for key " key ", is its value a number?" \
> " Falling back to default value of `%s`.", #val);
>
> - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - minuid = (uid_t)val;
> - minuid_set = 1;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
> - minuid = FALLBACK_MINUID;
> - minuid_set = 1;
> - }
> - }
> - free(path);
> - path = NULL;
> + uid_t minuid;
> + bool fallback_set;
> + if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid, &fallback_set))
> + genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
>
> - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - maxuid = (uid_t)val;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
> - maxuid = FALLBACK_MAXUID;
> - }
> - }
> - free(path);
> - path = NULL;
> + const bool logindefs_minuid_fallback_set = fallback_set;
>
> - path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - temp = (uid_t)val;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> - temp = FALLBACK_LU_UIDNUMBER;
> - }
> - if (!minuid_set || temp < minuid) {
> - minuid = temp;
> - minuid_set = 1;
> - }
> - }
> - free(path);
> - path = NULL;
> + uid_t temp;
> + if (!parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp, &fallback_set))
> + genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> +
> + if (logindefs_minuid_fallback_set)
> + minuid = temp;
> +
> + uid_t maxuid;
> + /* We don't actually check fallback_set here, PATH_ETC_LOGIN_DEFS is the one source of
> + truth for UID_MAX. */
> + if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid, &fallback_set))
> + genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
>
> #undef genhomedircon_warn_conv_fail
>
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4] genhomedircon: cleanup parsing of uid config values
2025-10-24 19:29 ` Stephen Smalley
@ 2025-10-26 19:13 ` Rahul Sandhu
2025-10-27 13:10 ` Stephen Smalley
2025-10-27 16:54 ` Stephen Smalley
0 siblings, 2 replies; 10+ messages in thread
From: Rahul Sandhu @ 2025-10-26 19:13 UTC (permalink / raw)
To: stephen.smalley.work; +Cc: nvraxn, selinux, hylandb256, Hyland B.
Parsing KV files with a separator of similar format is fairly similar,
so we may as well add a helper function to make it easier to read.
Credit to Hyland for reminding me to check for ERANGE.
Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
Reviewed-by: Hyland B. <me@ow.swag.toys>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
---
libsemanage/src/genhomedircon.c | 107 +++++++++++++++++---------------
1 file changed, 57 insertions(+), 50 deletions(-)
v2: rename path to something more sensible (afterall, we are parsing a
UID!) and move the free to later, just before both return paths to
not dereference it when checking whether we actually parsed a valid
number or not.
v3: handle the fallback case for minuid properly such that we don't end
up always using a fallback if minuid is not set in login.defs, and
return a bool instead as it's a bit more sensible for what we're
trying to return. Also, check for ERANGE.
v4: add credit to Hyland for reminding me to check for ERANGE.
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index 34056562..e91c64e6 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -308,14 +308,52 @@ done:
return retval;
}
+/*
+ * Parses `file` for `key` seperated by `sep` into `out`.
+ * Returns:
+ * true on success.
+ * false on failure.
+ * `out` is guaranteed to be initalised.
+ * `fallback_set` is initalised to false, and set to true if a fallback was used.
+ */
+static bool parse_uid_config(const char *file, const char *key, const char *sep,
+ uid_t fallback, uid_t *out, bool *fallback_set)
+{
+ assert(out);
+ assert(fallback_set);
+
+ *fallback_set = false;
+
+ char *uid_str = semanage_findval(file, key, sep);
+ if (!uid_str || !*uid_str) {
+ free(uid_str);
+ *fallback_set = true;
+ *out = fallback;
+ return true;
+ }
+
+ char *endptr;
+ errno = 0;
+ const unsigned long val = strtoul(uid_str, &endptr, 0);
+
+ if (endptr != uid_str && *endptr == '\0' && errno != ERANGE) {
+ *out = (uid_t)val;
+ free(uid_str);
+ return true;
+ }
+
+ free(uid_str);
+ *fallback_set = true;
+ *out = fallback;
+ return false;
+}
+
static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
{
semanage_list_t *homedir_list = NULL;
semanage_list_t *shells = NULL;
fc_match_handle_t hand;
char *path = NULL;
- uid_t temp, minuid = 500, maxuid = 60000;
- int minuid_set = 0;
struct passwd *pwbuf;
struct stat buf;
@@ -362,56 +400,25 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
"Conversion failed for key " key ", is its value a number?" \
" Falling back to default value of `%s`.", #val);
- path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- minuid = (uid_t)val;
- minuid_set = 1;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
- minuid = FALLBACK_MINUID;
- minuid_set = 1;
- }
- }
- free(path);
- path = NULL;
+ uid_t minuid;
+ bool fallback_set;
+ if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid, &fallback_set))
+ genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
- path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- maxuid = (uid_t)val;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
- maxuid = FALLBACK_MAXUID;
- }
- }
- free(path);
- path = NULL;
+ const bool logindefs_minuid_fallback_set = fallback_set;
- path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
- if (path && *path) {
- char *endptr;
- const unsigned long val = strtoul(path, &endptr, 0);
- if (endptr != path && *endptr == '\0') {
- temp = (uid_t)val;
- } else {
- /* we were provided an invalid value, use defaults. */
- genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
- temp = FALLBACK_LU_UIDNUMBER;
- }
- if (!minuid_set || temp < minuid) {
- minuid = temp;
- minuid_set = 1;
- }
- }
- free(path);
- path = NULL;
+ uid_t temp;
+ if (!parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp, &fallback_set))
+ genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
+
+ if (logindefs_minuid_fallback_set)
+ minuid = temp;
+
+ uid_t maxuid;
+ /* We don't actually check fallback_set here, PATH_ETC_LOGIN_DEFS is the one source of
+ truth for UID_MAX. */
+ if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid, &fallback_set))
+ genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
#undef genhomedircon_warn_conv_fail
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v4] genhomedircon: cleanup parsing of uid config values
2025-10-26 19:13 ` [PATCH v4] " Rahul Sandhu
@ 2025-10-27 13:10 ` Stephen Smalley
2025-10-27 13:12 ` Stephen Smalley
2025-10-27 16:54 ` Stephen Smalley
1 sibling, 1 reply; 10+ messages in thread
From: Stephen Smalley @ 2025-10-27 13:10 UTC (permalink / raw)
To: Rahul Sandhu; +Cc: selinux, hylandb256, Hyland B.
On Sun, Oct 26, 2025 at 3:13 PM Rahul Sandhu <nvraxn@gmail.com> wrote:
>
> Parsing KV files with a separator of similar format is fairly similar,
> so we may as well add a helper function to make it easier to read.
>
> Credit to Hyland for reminding me to check for ERANGE.
>
> Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
> Reviewed-by: Hyland B. <me@ow.swag.toys>
I don't see any such email from Hyland, just this from you, possibly
it was bounced by the list or eaten by spam filters?
> Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> ---
> libsemanage/src/genhomedircon.c | 107 +++++++++++++++++---------------
> 1 file changed, 57 insertions(+), 50 deletions(-)
>
> v2: rename path to something more sensible (afterall, we are parsing a
> UID!) and move the free to later, just before both return paths to
> not dereference it when checking whether we actually parsed a valid
> number or not.
> v3: handle the fallback case for minuid properly such that we don't end
> up always using a fallback if minuid is not set in login.defs, and
> return a bool instead as it's a bit more sensible for what we're
> trying to return. Also, check for ERANGE.
> v4: add credit to Hyland for reminding me to check for ERANGE.
>
> diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
> index 34056562..e91c64e6 100644
> --- a/libsemanage/src/genhomedircon.c
> +++ b/libsemanage/src/genhomedircon.c
> @@ -308,14 +308,52 @@ done:
> return retval;
> }
>
> +/*
> + * Parses `file` for `key` seperated by `sep` into `out`.
> + * Returns:
> + * true on success.
> + * false on failure.
> + * `out` is guaranteed to be initalised.
> + * `fallback_set` is initalised to false, and set to true if a fallback was used.
> + */
> +static bool parse_uid_config(const char *file, const char *key, const char *sep,
> + uid_t fallback, uid_t *out, bool *fallback_set)
> +{
> + assert(out);
> + assert(fallback_set);
> +
> + *fallback_set = false;
> +
> + char *uid_str = semanage_findval(file, key, sep);
> + if (!uid_str || !*uid_str) {
> + free(uid_str);
> + *fallback_set = true;
> + *out = fallback;
> + return true;
> + }
> +
> + char *endptr;
> + errno = 0;
> + const unsigned long val = strtoul(uid_str, &endptr, 0);
> +
> + if (endptr != uid_str && *endptr == '\0' && errno != ERANGE) {
> + *out = (uid_t)val;
> + free(uid_str);
> + return true;
> + }
> +
> + free(uid_str);
> + *fallback_set = true;
> + *out = fallback;
> + return false;
> +}
> +
> static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> {
> semanage_list_t *homedir_list = NULL;
> semanage_list_t *shells = NULL;
> fc_match_handle_t hand;
> char *path = NULL;
> - uid_t temp, minuid = 500, maxuid = 60000;
> - int minuid_set = 0;
> struct passwd *pwbuf;
> struct stat buf;
>
> @@ -362,56 +400,25 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> "Conversion failed for key " key ", is its value a number?" \
> " Falling back to default value of `%s`.", #val);
>
> - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - minuid = (uid_t)val;
> - minuid_set = 1;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
> - minuid = FALLBACK_MINUID;
> - minuid_set = 1;
> - }
> - }
> - free(path);
> - path = NULL;
> + uid_t minuid;
> + bool fallback_set;
> + if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid, &fallback_set))
> + genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
>
> - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - maxuid = (uid_t)val;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
> - maxuid = FALLBACK_MAXUID;
> - }
> - }
> - free(path);
> - path = NULL;
> + const bool logindefs_minuid_fallback_set = fallback_set;
>
> - path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - temp = (uid_t)val;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> - temp = FALLBACK_LU_UIDNUMBER;
> - }
> - if (!minuid_set || temp < minuid) {
> - minuid = temp;
> - minuid_set = 1;
> - }
> - }
> - free(path);
> - path = NULL;
> + uid_t temp;
> + if (!parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp, &fallback_set))
> + genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> +
> + if (logindefs_minuid_fallback_set)
> + minuid = temp;
> +
> + uid_t maxuid;
> + /* We don't actually check fallback_set here, PATH_ETC_LOGIN_DEFS is the one source of
> + truth for UID_MAX. */
> + if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid, &fallback_set))
> + genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
>
> #undef genhomedircon_warn_conv_fail
>
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4] genhomedircon: cleanup parsing of uid config values
2025-10-27 13:10 ` Stephen Smalley
@ 2025-10-27 13:12 ` Stephen Smalley
0 siblings, 0 replies; 10+ messages in thread
From: Stephen Smalley @ 2025-10-27 13:12 UTC (permalink / raw)
To: Rahul Sandhu; +Cc: selinux, hylandb256
On Mon, Oct 27, 2025 at 9:10 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
>
> On Sun, Oct 26, 2025 at 3:13 PM Rahul Sandhu <nvraxn@gmail.com> wrote:
> >
> > Parsing KV files with a separator of similar format is fairly similar,
> > so we may as well add a helper function to make it easier to read.
> >
> > Credit to Hyland for reminding me to check for ERANGE.
> >
> > Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
> > Reviewed-by: Hyland B. <me@ow.swag.toys>
>
> I don't see any such email from Hyland, just this from you, possibly
> it was bounced by the list or eaten by spam filters?
That address bounces with no such domain, so I am not taking this as a
Reviewed-by tag.
>
> > Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> > ---
> > libsemanage/src/genhomedircon.c | 107 +++++++++++++++++---------------
> > 1 file changed, 57 insertions(+), 50 deletions(-)
> >
> > v2: rename path to something more sensible (afterall, we are parsing a
> > UID!) and move the free to later, just before both return paths to
> > not dereference it when checking whether we actually parsed a valid
> > number or not.
> > v3: handle the fallback case for minuid properly such that we don't end
> > up always using a fallback if minuid is not set in login.defs, and
> > return a bool instead as it's a bit more sensible for what we're
> > trying to return. Also, check for ERANGE.
> > v4: add credit to Hyland for reminding me to check for ERANGE.
> >
> > diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
> > index 34056562..e91c64e6 100644
> > --- a/libsemanage/src/genhomedircon.c
> > +++ b/libsemanage/src/genhomedircon.c
> > @@ -308,14 +308,52 @@ done:
> > return retval;
> > }
> >
> > +/*
> > + * Parses `file` for `key` seperated by `sep` into `out`.
> > + * Returns:
> > + * true on success.
> > + * false on failure.
> > + * `out` is guaranteed to be initalised.
> > + * `fallback_set` is initalised to false, and set to true if a fallback was used.
> > + */
> > +static bool parse_uid_config(const char *file, const char *key, const char *sep,
> > + uid_t fallback, uid_t *out, bool *fallback_set)
> > +{
> > + assert(out);
> > + assert(fallback_set);
> > +
> > + *fallback_set = false;
> > +
> > + char *uid_str = semanage_findval(file, key, sep);
> > + if (!uid_str || !*uid_str) {
> > + free(uid_str);
> > + *fallback_set = true;
> > + *out = fallback;
> > + return true;
> > + }
> > +
> > + char *endptr;
> > + errno = 0;
> > + const unsigned long val = strtoul(uid_str, &endptr, 0);
> > +
> > + if (endptr != uid_str && *endptr == '\0' && errno != ERANGE) {
> > + *out = (uid_t)val;
> > + free(uid_str);
> > + return true;
> > + }
> > +
> > + free(uid_str);
> > + *fallback_set = true;
> > + *out = fallback;
> > + return false;
> > +}
> > +
> > static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> > {
> > semanage_list_t *homedir_list = NULL;
> > semanage_list_t *shells = NULL;
> > fc_match_handle_t hand;
> > char *path = NULL;
> > - uid_t temp, minuid = 500, maxuid = 60000;
> > - int minuid_set = 0;
> > struct passwd *pwbuf;
> > struct stat buf;
> >
> > @@ -362,56 +400,25 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> > "Conversion failed for key " key ", is its value a number?" \
> > " Falling back to default value of `%s`.", #val);
> >
> > - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
> > - if (path && *path) {
> > - char *endptr;
> > - const unsigned long val = strtoul(path, &endptr, 0);
> > - if (endptr != path && *endptr == '\0') {
> > - minuid = (uid_t)val;
> > - minuid_set = 1;
> > - } else {
> > - /* we were provided an invalid value, use defaults. */
> > - genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
> > - minuid = FALLBACK_MINUID;
> > - minuid_set = 1;
> > - }
> > - }
> > - free(path);
> > - path = NULL;
> > + uid_t minuid;
> > + bool fallback_set;
> > + if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid, &fallback_set))
> > + genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
> >
> > - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
> > - if (path && *path) {
> > - char *endptr;
> > - const unsigned long val = strtoul(path, &endptr, 0);
> > - if (endptr != path && *endptr == '\0') {
> > - maxuid = (uid_t)val;
> > - } else {
> > - /* we were provided an invalid value, use defaults. */
> > - genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
> > - maxuid = FALLBACK_MAXUID;
> > - }
> > - }
> > - free(path);
> > - path = NULL;
> > + const bool logindefs_minuid_fallback_set = fallback_set;
> >
> > - path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
> > - if (path && *path) {
> > - char *endptr;
> > - const unsigned long val = strtoul(path, &endptr, 0);
> > - if (endptr != path && *endptr == '\0') {
> > - temp = (uid_t)val;
> > - } else {
> > - /* we were provided an invalid value, use defaults. */
> > - genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> > - temp = FALLBACK_LU_UIDNUMBER;
> > - }
> > - if (!minuid_set || temp < minuid) {
> > - minuid = temp;
> > - minuid_set = 1;
> > - }
> > - }
> > - free(path);
> > - path = NULL;
> > + uid_t temp;
> > + if (!parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp, &fallback_set))
> > + genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> > +
> > + if (logindefs_minuid_fallback_set)
> > + minuid = temp;
> > +
> > + uid_t maxuid;
> > + /* We don't actually check fallback_set here, PATH_ETC_LOGIN_DEFS is the one source of
> > + truth for UID_MAX. */
> > + if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid, &fallback_set))
> > + genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
> >
> > #undef genhomedircon_warn_conv_fail
> >
> > --
> > 2.51.0
> >
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4] genhomedircon: cleanup parsing of uid config values
2025-10-26 19:13 ` [PATCH v4] " Rahul Sandhu
2025-10-27 13:10 ` Stephen Smalley
@ 2025-10-27 16:54 ` Stephen Smalley
1 sibling, 0 replies; 10+ messages in thread
From: Stephen Smalley @ 2025-10-27 16:54 UTC (permalink / raw)
To: Rahul Sandhu; +Cc: selinux, hhhyland.belcherrr4
On Sun, Oct 26, 2025 at 3:13 PM Rahul Sandhu <nvraxn@gmail.com> wrote:
>
> Parsing KV files with a separator of similar format is fairly similar,
> so we may as well add a helper function to make it easier to read.
>
> Credit to Hyland for reminding me to check for ERANGE.
>
> Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
> Reviewed-by: Hyland Belcher <hhhyland.belcherrr4@gmail.com>
> Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Thanks, applied with the corrected tag.
> ---
> libsemanage/src/genhomedircon.c | 107 +++++++++++++++++---------------
> 1 file changed, 57 insertions(+), 50 deletions(-)
>
> v2: rename path to something more sensible (afterall, we are parsing a
> UID!) and move the free to later, just before both return paths to
> not dereference it when checking whether we actually parsed a valid
> number or not.
> v3: handle the fallback case for minuid properly such that we don't end
> up always using a fallback if minuid is not set in login.defs, and
> return a bool instead as it's a bit more sensible for what we're
> trying to return. Also, check for ERANGE.
> v4: add credit to Hyland for reminding me to check for ERANGE.
>
> diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
> index 34056562..e91c64e6 100644
> --- a/libsemanage/src/genhomedircon.c
> +++ b/libsemanage/src/genhomedircon.c
> @@ -308,14 +308,52 @@ done:
> return retval;
> }
>
> +/*
> + * Parses `file` for `key` seperated by `sep` into `out`.
> + * Returns:
> + * true on success.
> + * false on failure.
> + * `out` is guaranteed to be initalised.
> + * `fallback_set` is initalised to false, and set to true if a fallback was used.
> + */
> +static bool parse_uid_config(const char *file, const char *key, const char *sep,
> + uid_t fallback, uid_t *out, bool *fallback_set)
> +{
> + assert(out);
> + assert(fallback_set);
> +
> + *fallback_set = false;
> +
> + char *uid_str = semanage_findval(file, key, sep);
> + if (!uid_str || !*uid_str) {
> + free(uid_str);
> + *fallback_set = true;
> + *out = fallback;
> + return true;
> + }
> +
> + char *endptr;
> + errno = 0;
> + const unsigned long val = strtoul(uid_str, &endptr, 0);
> +
> + if (endptr != uid_str && *endptr == '\0' && errno != ERANGE) {
> + *out = (uid_t)val;
> + free(uid_str);
> + return true;
> + }
> +
> + free(uid_str);
> + *fallback_set = true;
> + *out = fallback;
> + return false;
> +}
> +
> static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> {
> semanage_list_t *homedir_list = NULL;
> semanage_list_t *shells = NULL;
> fc_match_handle_t hand;
> char *path = NULL;
> - uid_t temp, minuid = 500, maxuid = 60000;
> - int minuid_set = 0;
> struct passwd *pwbuf;
> struct stat buf;
>
> @@ -362,56 +400,25 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
> "Conversion failed for key " key ", is its value a number?" \
> " Falling back to default value of `%s`.", #val);
>
> - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - minuid = (uid_t)val;
> - minuid_set = 1;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
> - minuid = FALLBACK_MINUID;
> - minuid_set = 1;
> - }
> - }
> - free(path);
> - path = NULL;
> + uid_t minuid;
> + bool fallback_set;
> + if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid, &fallback_set))
> + genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
>
> - path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - maxuid = (uid_t)val;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
> - maxuid = FALLBACK_MAXUID;
> - }
> - }
> - free(path);
> - path = NULL;
> + const bool logindefs_minuid_fallback_set = fallback_set;
>
> - path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
> - if (path && *path) {
> - char *endptr;
> - const unsigned long val = strtoul(path, &endptr, 0);
> - if (endptr != path && *endptr == '\0') {
> - temp = (uid_t)val;
> - } else {
> - /* we were provided an invalid value, use defaults. */
> - genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> - temp = FALLBACK_LU_UIDNUMBER;
> - }
> - if (!minuid_set || temp < minuid) {
> - minuid = temp;
> - minuid_set = 1;
> - }
> - }
> - free(path);
> - path = NULL;
> + uid_t temp;
> + if (!parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp, &fallback_set))
> + genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
> +
> + if (logindefs_minuid_fallback_set)
> + minuid = temp;
> +
> + uid_t maxuid;
> + /* We don't actually check fallback_set here, PATH_ETC_LOGIN_DEFS is the one source of
> + truth for UID_MAX. */
> + if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid, &fallback_set))
> + genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
>
> #undef genhomedircon_warn_conv_fail
>
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-10-27 16:54 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-21 11:36 [PATCH] genhomedircon: cleanup parsing of uid config values Rahul Sandhu
2025-10-21 13:15 ` Stephen Smalley
2025-10-22 0:01 ` [PATCH v2] " Rahul Sandhu
2025-10-22 14:51 ` Stephen Smalley
2025-10-24 8:07 ` [PATCH v3] " Rahul Sandhu
2025-10-24 19:29 ` Stephen Smalley
2025-10-26 19:13 ` [PATCH v4] " Rahul Sandhu
2025-10-27 13:10 ` Stephen Smalley
2025-10-27 13:12 ` Stephen Smalley
2025-10-27 16:54 ` Stephen Smalley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).