commit 6b209c4
Emilia Smólska
·
2026-07-26 09:21:17 +0000 UTC
parent 3a7962b
setusercontext
3 files changed,
+36,
-16
+7,
-2
1@@ -16,10 +16,15 @@
2 #define HAVE_PLEDGE
3 #endif
4
5-/* setclasscontext library function present */
6+/* login_cap.h present */
7 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
8-#define HAVE_SETCLASSCONTEXT
9+#define HAVE_LOGIN_CAP
10 #endif
11+#ifdef __has_include
12+#if __has_include(<login_cap.h>)
13+#define HAVE_LOGIN_CAP
14+#endif
15+#endif
16
17 /* for compilers without attribute support */
18 /* #define __attribute(_) */
+4,
-4
1@@ -9,7 +9,7 @@
2 .Sh SYNOPSIS
3 .Nm
4 .Op Fl n
5-#ifdef HAVE_SETCLASSCONTEXT
6+#ifdef HAVE_LOGIN_CAP
7 .Op Fl c Ar class
8 #endif
9 .Op Fl G Ar gid
10@@ -29,7 +29,7 @@ utility allows a user to run a command
11 if no command is specified
12 .Pc
13 with a different
14-#ifdef HAVE_SETCLASSCONTEXT
15+#ifdef HAVE_LOGIN_CAP
16 login class,
17 #endif
18 group id,
19@@ -41,7 +41,7 @@ write permission on
20 .Pa CHECKFILE .
21 The options are as follows:
22 .Bl -tag -width 8n
23-#ifdef HAVE_SETCLASSCONTEXT
24+#ifdef HAVE_LOGIN_CAP
25 .It Fl c Ar class
26 Specify a login class.
27 #endif
28@@ -92,7 +92,7 @@ authorized.
29 .Xr chroot 1 ,
30 #endif
31 .Xr doas 1 ,
32-#ifdef HAVE_SETCLASSCONTEXT
33+#ifdef HAVE_LOGIN_CAP
34 .Xr login 1 ,
35 #endif
36 .Xr su 1 ,
M
verily.c
+25,
-10
1@@ -13,7 +13,7 @@
2 #include "arg.h"
3 #include "config"
4
5-#ifdef HAVE_SETCLASSCONTEXT
6+#ifdef HAVE_LOGIN_CAP
7 #include <login_cap.h>
8 #endif
9
10@@ -29,6 +29,7 @@ char *argv0;
11 __attribute((format(printf, 1, 2)))
12 static noreturn void die(char *, ...);
13 static noreturn void usage(void);
14+static void dosetuid(uid_t, struct passwd *);
15
16 int
17 main(int argc, char **argv)
18@@ -65,11 +66,10 @@ main(int argc, char **argv)
19 die(CHECKFILESTR ": %s", strerror(errno));
20
21 if(argc <= 1 || argv[1][0] != '-')
22- if(setuid(0) < 0)
23- die("setuid 0: %s", strerror(errno));
24+ dosetuid(0, nil);
25
26 ARGBEGIN{
27-#ifdef HAVE_SETCLASSCONTEXT
28+#ifdef HAVE_LOGIN_CAP
29 case 'c': {
30 arg = EARGF(usage());
31 if(setclasscontext(arg, LOGIN_SETALL) < 0)
32@@ -120,8 +120,7 @@ main(int argc, char **argv)
33 uid = strtol(arg, &end, 10);
34 if(arg[0] == '\0' || end[0] != '\0')
35 usage();
36- if(setuid(uid) < 0)
37- die("setuid %u: %s", uid, strerror(errno));
38+ dosetuid(uid, nil);
39 break;
40 }
41 case 'u': {
42@@ -131,8 +130,7 @@ main(int argc, char **argv)
43 passwd = getpwnam(arg);
44 if(!passwd)
45 die("%s: No such user", arg);
46- if(setuid(passwd->pw_uid) < 0)
47- die("setuid %u: %s", passwd->pw_uid, strerror(errno));
48+ dosetuid(passwd->pw_uid, passwd);
49 break;
50 }
51 default:
52@@ -172,13 +170,30 @@ static noreturn void
53 usage(void)
54 {
55 fprintf(stderr, "usage: %s [-n]"
56-#if defined(HAVE_SETCLASSCONTEXT)
57+#ifdef HAVE_LOGIN_CAP
58 "[-c class] "
59 #endif
60 "[-G gid] [-g group] "
61-#if defined(WITH_CHROOT)
62+#ifdef WITH_CHROOT
63 "[-r dir] "
64 #endif
65 "[-U uid] [-u user]\n", argv0);
66 exit(1);
67 }
68+
69+static void
70+dosetuid(uid_t uid, struct passwd *passwd)
71+{
72+#ifdef HAVE_LOGIN_CAP
73+ if(!passwd)
74+ passwd = getpwuid(uid);
75+ if(!passwd)
76+ die("%u: No such user id", uid);
77+ if(setusercontext(nil, passwd, uid, LOGIN_SETALL) < 0)
78+ die("setusercontext: %s", strerror(errno));
79+#else
80+ (void)passwd;
81+ if(setuid(uid) < 0)
82+ die("setuid %u: %s", uid, strerror(errno));
83+#endif
84+}