git: 91eb4d2ba4de - main - chroot: slightly cleanup
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 03 Aug 2025 04:15:33 UTC
The branch main has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=91eb4d2ba4def0fe0f56f0a61ad7c503fcab891b
commit 91eb4d2ba4def0fe0f56f0a61ad7c503fcab891b
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-08-03 04:15:03 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-08-03 04:15:03 +0000
chroot: slightly cleanup
Highlights:
- Pull resolve_user() and resolve_group() out to make the main flow
a bit easier to read
- Fix some edge-cases in user/group resolution: you can have fully
numeric usernames, and they may or may not live within the valid
ID range. Switch to just trying to resolve every specified
group/user as a name, first, with a fallback to converting it to a
numeric type and trying to resolve it as an ID.
- Constify locals in main() that don't need to be mutable, re-sort
Reviewed by: emaste, olce
Differential Revision: https://reviews.freebsd.org/D51509
---
usr.sbin/chroot/chroot.c | 94 ++++++++++++++++++++++++++----------------------
1 file changed, 51 insertions(+), 43 deletions(-)
diff --git a/usr.sbin/chroot/chroot.c b/usr.sbin/chroot/chroot.c
index c978fc019c95..8a99a9bbf7cb 100644
--- a/usr.sbin/chroot/chroot.c
+++ b/usr.sbin/chroot/chroot.c
@@ -47,17 +47,58 @@
static void usage(void) __dead2;
+static gid_t
+resolve_group(const char *group)
+{
+ char *endp;
+ struct group *gp;
+ unsigned long gid;
+
+ gp = getgrnam(group);
+ if (gp != NULL)
+ return (gp->gr_gid);
+
+ /*
+ * Numeric IDs don't need a trip through the database to check them,
+ * POSIX seems to think we should generally accept a numeric ID as long
+ * as it's within the valid range.
+ */
+ errno = 0;
+ gid = strtoul(group, &endp, 0);
+ if (errno == 0 && *endp == '\0' && (gid_t)gid >= 0 && gid <= GID_MAX)
+ return (gid);
+
+ errx(1, "no such group '%s'", group);
+}
+
+static uid_t
+resolve_user(const char *user)
+{
+ char *endp;
+ struct passwd *pw;
+ unsigned long uid;
+
+ pw = getpwnam(user);
+ if (pw != NULL)
+ return (pw->pw_uid);
+
+ errno = 0;
+ uid = strtoul(user, &endp, 0);
+ if (errno == 0 && *endp == '\0' && (uid_t)uid >= 0 && uid <= UID_MAX)
+ return (uid);
+
+ errx(1, "no such user '%s'", user);
+}
+
int
main(int argc, char *argv[])
{
- struct group *gp;
- struct passwd *pw;
- char *endp, *p, *user, *group, *grouplist;
- const char *shell;
+ const char *group, *p, *shell, *user;
+ char *grouplist;
+ long ngroups_max;
gid_t gid, *gidlist;
uid_t uid;
int arg, ch, error, gids;
- long ngroups_max;
bool nonprivileged;
gid = 0;
@@ -95,19 +136,8 @@ main(int argc, char *argv[])
if (argc < 1)
usage();
- if (group != NULL) {
- if (isdigit((unsigned char)*group)) {
- gid = (gid_t)strtoul(group, &endp, 0);
- if (*endp != '\0')
- goto getgroup;
- } else {
- getgroup:
- if ((gp = getgrnam(group)) != NULL)
- gid = gp->gr_gid;
- else
- errx(1, "no such group `%s'", group);
- }
- }
+ if (group != NULL)
+ gid = resolve_group(group);
ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
if ((gidlist = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
@@ -122,35 +152,13 @@ main(int argc, char *argv[])
if (*p == '\0')
continue;
- if (isdigit((unsigned char)*p)) {
- gidlist[gids] = (gid_t)strtoul(p, &endp, 0);
- if (*endp != '\0')
- goto getglist;
- } else {
- getglist:
- if ((gp = getgrnam(p)) != NULL)
- gidlist[gids] = gp->gr_gid;
- else
- errx(1, "no such group `%s'", p);
- }
- gids++;
+ gidlist[gids++] = resolve_group(p);
}
if (p != NULL && gids == ngroups_max)
errx(1, "too many supplementary groups provided");
- if (user != NULL) {
- if (isdigit((unsigned char)*user)) {
- uid = (uid_t)strtoul(user, &endp, 0);
- if (*endp != '\0')
- goto getuser;
- } else {
- getuser:
- if ((pw = getpwnam(user)) != NULL)
- uid = pw->pw_uid;
- else
- errx(1, "no such user `%s'", user);
- }
- }
+ if (user != NULL)
+ uid = resolve_user(user);
if (nonprivileged) {
arg = PROC_NO_NEW_PRIVS_ENABLE;