Skip to content

Commit 45776a9

Browse files
WavyEbuilderstephensmalley
authored andcommitted
genhomedircon: cleanup parsing of uid config values
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 <[email protected]> Reviewed-by: Hyland Belcher <[email protected]> Acked-by: Stephen Smalley <[email protected]>
1 parent 221e289 commit 45776a9

File tree

1 file changed

+57
-50
lines changed

1 file changed

+57
-50
lines changed

libsemanage/src/genhomedircon.c

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -308,14 +308,52 @@ static int fcontext_matches(const semanage_fcontext_t *fcontext, void *varg)
308308
return retval;
309309
}
310310

311+
/*
312+
* Parses `file` for `key` seperated by `sep` into `out`.
313+
* Returns:
314+
* true on success.
315+
* false on failure.
316+
* `out` is guaranteed to be initalised.
317+
* `fallback_set` is initalised to false, and set to true if a fallback was used.
318+
*/
319+
static bool parse_uid_config(const char *file, const char *key, const char *sep,
320+
uid_t fallback, uid_t *out, bool *fallback_set)
321+
{
322+
assert(out);
323+
assert(fallback_set);
324+
325+
*fallback_set = false;
326+
327+
char *uid_str = semanage_findval(file, key, sep);
328+
if (!uid_str || !*uid_str) {
329+
free(uid_str);
330+
*fallback_set = true;
331+
*out = fallback;
332+
return true;
333+
}
334+
335+
char *endptr;
336+
errno = 0;
337+
const unsigned long val = strtoul(uid_str, &endptr, 0);
338+
339+
if (endptr != uid_str && *endptr == '\0' && errno != ERANGE) {
340+
*out = (uid_t)val;
341+
free(uid_str);
342+
return true;
343+
}
344+
345+
free(uid_str);
346+
*fallback_set = true;
347+
*out = fallback;
348+
return false;
349+
}
350+
311351
static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
312352
{
313353
semanage_list_t *homedir_list = NULL;
314354
semanage_list_t *shells = NULL;
315355
fc_match_handle_t hand;
316356
char *path = NULL;
317-
uid_t temp, minuid = 500, maxuid = 60000;
318-
int minuid_set = 0;
319357
struct passwd *pwbuf;
320358
struct stat buf;
321359

@@ -362,56 +400,25 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s)
362400
"Conversion failed for key " key ", is its value a number?" \
363401
" Falling back to default value of `%s`.", #val);
364402

365-
path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL);
366-
if (path && *path) {
367-
char *endptr;
368-
const unsigned long val = strtoul(path, &endptr, 0);
369-
if (endptr != path && *endptr == '\0') {
370-
minuid = (uid_t)val;
371-
minuid_set = 1;
372-
} else {
373-
/* we were provided an invalid value, use defaults. */
374-
genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
375-
minuid = FALLBACK_MINUID;
376-
minuid_set = 1;
377-
}
378-
}
379-
free(path);
380-
path = NULL;
403+
uid_t minuid;
404+
bool fallback_set;
405+
if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL, FALLBACK_MINUID, &minuid, &fallback_set))
406+
genhomedircon_warn_conv_fail("UID_MIN", FALLBACK_MINUID);
381407

382-
path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL);
383-
if (path && *path) {
384-
char *endptr;
385-
const unsigned long val = strtoul(path, &endptr, 0);
386-
if (endptr != path && *endptr == '\0') {
387-
maxuid = (uid_t)val;
388-
} else {
389-
/* we were provided an invalid value, use defaults. */
390-
genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
391-
maxuid = FALLBACK_MAXUID;
392-
}
393-
}
394-
free(path);
395-
path = NULL;
408+
const bool logindefs_minuid_fallback_set = fallback_set;
396409

397-
path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=");
398-
if (path && *path) {
399-
char *endptr;
400-
const unsigned long val = strtoul(path, &endptr, 0);
401-
if (endptr != path && *endptr == '\0') {
402-
temp = (uid_t)val;
403-
} else {
404-
/* we were provided an invalid value, use defaults. */
405-
genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
406-
temp = FALLBACK_LU_UIDNUMBER;
407-
}
408-
if (!minuid_set || temp < minuid) {
409-
minuid = temp;
410-
minuid_set = 1;
411-
}
412-
}
413-
free(path);
414-
path = NULL;
410+
uid_t temp;
411+
if (!parse_uid_config(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "=", FALLBACK_LU_UIDNUMBER, &temp, &fallback_set))
412+
genhomedircon_warn_conv_fail("LU_UIDNUMBER", FALLBACK_LU_UIDNUMBER);
413+
414+
if (logindefs_minuid_fallback_set)
415+
minuid = temp;
416+
417+
uid_t maxuid;
418+
/* We don't actually check fallback_set here, PATH_ETC_LOGIN_DEFS is the one source of
419+
truth for UID_MAX. */
420+
if (!parse_uid_config(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL, FALLBACK_MAXUID, &maxuid, &fallback_set))
421+
genhomedircon_warn_conv_fail("UID_MAX", FALLBACK_MAXUID);
415422

416423
#undef genhomedircon_warn_conv_fail
417424

0 commit comments

Comments
 (0)