Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108593926
D45145.id138588.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D45145.id138588.diff
View Options
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -288,6 +288,7 @@
mac_biba.4 \
mac_bsdextended.4 \
mac_ddb.4 \
+ mac_do.4 \
mac_ifoff.4 \
mac_ipacl.4 \
mac_lomac.4 \
diff --git a/share/man/man4/mac_do.4 b/share/man/man4/mac_do.4
new file mode 100644
--- /dev/null
+++ b/share/man/man4/mac_do.4
@@ -0,0 +1,62 @@
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2024 Baptiste Daroussin <bapt@FreeBSD.org>
+.Dd May 9, 2024
+.Dt MAC_DO 4
+.Os
+.Sh NAME
+.Nm mac_do
+.Nd "policy allowing user to execute program as another user"
+.Sh SYNOPSIS
+To compile the
+.Nm
+policy into your kernel, place the following lines
+in your kernel configruation file:
+.Bd -ragged -offset indent
+.Cd "options MAC"
+.Cd "options MAC_DO"
+.Ed
+.Pp
+.Sh DESCRIPTION
+The
+.Nm
+policy grants some user the ability to run a process as another user
+according to rules.
+.Pp
+The exact set of kernel privileges granted are:
+.Bl -inset -compact -offset indent
+.It Dv PRIV_CRED_SETGROUPS
+.It Dv PRIV_CRET_SETUID
+.El
+The following
+.Xr sysctl 8
+MIBs are available:
+.Bl -tag -width indent
+.It Va security.mac.do.enabled
+Enable the
+.Nm
+policy.
+(Default: 1).
+.It Va security.mac.do.rules
+The set of rules.
+.El
+.Pp
+The rules consist of a list of elements separated by
+.So , Sc .
+Each elements is in the following form
+.Dq [uid|gid]=<fid>:<tid>
+Where
+.Ar fid
+is the uid or the gid, depending on the modifier specified for the users allowed
+to become
+.Ar tid . and
+.Ar tid is the uid of the targetted user.
+2 special forms are accepted for
+.Ar tid :
+.Va any
+or
+.Va *
+which allows to target any users.
+.Sh SEE ALSO
+.Xr mac 4 ,
+.Xr mdo 1
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -226,6 +226,7 @@
${_mac_biba} \
${_mac_bsdextended} \
${_mac_ddb} \
+ ${_mac_do} \
${_mac_ifoff} \
${_mac_ipacl} \
${_mac_lomac} \
@@ -587,6 +588,7 @@
.if ${KERN_OPTS:MDDB} || defined(ALL_MODULES)
_mac_ddb= mac_ddb
.endif
+_mac_do= mac_do
_mac_ifoff= mac_ifoff
_mac_ipacl= mac_ipacl
_mac_lomac= mac_lomac
diff --git a/sys/modules/mac_do/Makefile b/sys/modules/mac_do/Makefile
new file mode 100644
--- /dev/null
+++ b/sys/modules/mac_do/Makefile
@@ -0,0 +1,6 @@
+.PATH: ${SRCTOP}/sys/security/mac_do
+
+KMOD= mac_do
+SRCS= mac_do.c vnode_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/security/mac_do/mac_do.c b/sys/security/mac_do/mac_do.c
new file mode 100644
--- /dev/null
+++ b/sys/security/mac_do/mac_do.c
@@ -0,0 +1,546 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright(c) 2024 Baptiste Daroussin <bapt@FreeBSD.org
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/ucred.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
+#include <sys/mutex.h>
+#include <sys/priv.h>
+#include <sys/malloc.h>
+#include <sys/jail.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+
+#include <security/mac/mac_policy.h>
+
+SYSCTL_DECL(_security_mac);
+
+static SYSCTL_NODE(_security_mac, OID_AUTO, do,
+ CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "mac_do policy controls");
+
+static int do_enabled = 1;
+SYSCTL_INT(_security_mac_do, OID_AUTO, enabled, CTLFLAG_RWTUN,
+ &do_enabled, 0, "Enforce do policy");
+
+static MALLOC_DEFINE(M_DO, "do_rule", "Rules for mac_do");
+
+#define MAC_RULE_STRING_LEN 1024
+
+static unsigned mac_do_osd_jail_slot;
+
+#define RULE_UID 1
+#define RULE_GID 2
+#define RULE_ANY 3
+
+struct rule {
+ int from_type;
+ union {
+ uid_t f_uid;
+ gid_t f_gid;
+ };
+ int to_type;
+ uid_t t_uid;
+ TAILQ_ENTRY(rule) r_entries;
+};
+
+struct mac_do_rule {
+ char string[MAC_RULE_STRING_LEN];
+ TAILQ_HEAD(rulehead, rule) head;
+};
+
+static struct mac_do_rule rules0;
+
+static void
+toast_rules(struct rulehead *head)
+{
+ struct rule *r;
+
+ while ((r = TAILQ_FIRST(head)) != NULL) {
+ TAILQ_REMOVE(head, r, r_entries);
+ free(r, M_DO);
+ }
+}
+
+static int
+parse_rule_element(char *element, struct rule **rule)
+{
+ int error = 0;
+ char *type, *id, *p;
+ struct rule *new;
+
+ new = malloc(sizeof(*new), M_DO, M_ZERO|M_WAITOK);
+
+ type = strsep(&element, "=");
+ if (type == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ if (strcmp(type, "uid") == 0) {
+ new->from_type = RULE_UID;
+ } else if (strcmp(type, "gid") == 0) {
+ new->from_type = RULE_GID;
+ } else {
+ error = EINVAL;
+ goto out;
+ }
+ id = strsep(&element, ":");
+ if (id == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ if (new->from_type == RULE_UID)
+ new->f_uid = strtol(id, &p, 10);
+ if (new->from_type == RULE_GID)
+ new->f_gid = strtol(id, &p, 10);
+ if (*p != '\0') {
+ error = EINVAL;
+ goto out;
+ }
+ if (*element == '\0') {
+ error = EINVAL;
+ goto out;
+ }
+ if (strcmp(element, "any") == 0 || strcmp(element, "*") == 0) {
+ new->to_type = RULE_ANY;
+ } else {
+ new->to_type = RULE_UID;
+ new->t_uid = strtol(element, &p, 10);
+ if (*p != '\0') {
+ error = EINVAL;
+ goto out;
+ }
+ }
+out:
+ if (error != 0) {
+ free(new, M_DO);
+ *rule = NULL;
+ } else
+ *rule = new;
+ return (error);
+}
+
+static int
+parse_rules(char *string, struct rulehead *head)
+{
+ struct rule *new;
+ char *element;
+ int error = 0;
+
+ while ((element = strsep(&string, ",")) != NULL) {
+ if (strlen(element) == 0)
+ continue;
+ error = parse_rule_element(element, &new);
+ if (error)
+ goto out;
+ TAILQ_INSERT_TAIL(head, new, r_entries);
+ }
+out:
+ if (error != 0)
+ toast_rules(head);
+ return (error);
+}
+
+static struct mac_do_rule *
+mac_do_rule_find(struct prison *spr, struct prison **prp)
+{
+ struct prison *pr;
+ struct mac_do_rule *rules;
+
+ for (pr = spr;; pr = pr->pr_parent) {
+ mtx_lock(&pr->pr_mtx);
+ if (pr == &prison0) {
+ rules = &rules0;
+ break;
+ }
+ rules = osd_jail_get(pr, mac_do_osd_jail_slot);
+ if (rules != NULL)
+ break;
+ mtx_unlock(&pr->pr_mtx);
+ }
+ *prp = pr;
+
+ return (rules);
+}
+
+static int
+sysctl_rules(SYSCTL_HANDLER_ARGS)
+{
+ char *copy_string, *new_string;
+ struct rulehead head, saved_head;
+ struct prison *pr;
+ struct mac_do_rule *rules;
+ int error;
+
+ rules = mac_do_rule_find(req->td->td_ucred->cr_prison, &pr);
+ mtx_unlock(&pr->pr_mtx);
+ if (req->newptr == NULL)
+ return (sysctl_handle_string(oidp, rules->string, MAC_RULE_STRING_LEN, req));
+
+ new_string = malloc(MAC_RULE_STRING_LEN, M_DO,
+ M_WAITOK|M_ZERO);
+ mtx_lock(&pr->pr_mtx);
+ strlcpy(new_string, rules->string, MAC_RULE_STRING_LEN);
+ mtx_unlock(pr->pr_mtx);
+
+ error = sysctl_handle_string(oidp, new_string, MAC_RULE_STRING_LEN, req);
+ if (error)
+ goto out;
+
+ copy_string = strdup(new_string, M_DO);
+ TAILQ_INIT(&head);
+ error = parse_rules(copy_string, &head);
+ free(copy_string, M_DO);
+ if (error)
+ goto out;
+ TAILQ_INIT(&saved_head);
+ mtx_lock(&pr->pr_mtx);
+ TAILQ_CONCAT(&saved_head, &rules->head, r_entries);
+ TAILQ_CONCAT(&(rules->head), &head, r_entries);
+ strlcpy(rules->string, new_string, MAC_RULE_STRING_LEN);
+ mtx_unlock(&pr->pr_mtx);
+ toast_rules(&saved_head);
+
+out:
+ free(new_string, M_DO);
+ return (error);
+}
+
+SYSCTL_PROC(_security_mac_do, OID_AUTO, rules,
+ CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE,
+ 0, 0, sysctl_rules, "A",
+ "Rules");
+
+static void
+destroy(struct mac_policy_conf *mpc)
+{
+ osd_jail_deregister(mac_do_osd_jail_slot);
+ toast_rules(&rules0.head);
+}
+
+static void
+mac_do_alloc_prison(struct prison *pr, struct mac_do_rule **lrp)
+{
+ struct prison *ppr;
+ struct mac_do_rule *rules, *nrules;
+ void **rsv;
+
+ rules = mac_do_rule_find(pr, &ppr);
+ if (ppr == pr)
+ goto done;
+
+ mtx_unlock(&ppr->pr_mtx);
+ nrules = malloc(sizeof(struct mac_do_rule), M_PRISON, M_WAITOK|M_ZERO);
+ rsv = osd_reserve(mac_do_osd_jail_slot);
+ rules = mac_do_rule_find(pr, &ppr);
+ if (ppr == pr) {
+ free(nrules, M_PRISON);
+ osd_free_reserved(rsv);
+ goto done;
+ }
+ mtx_lock(&pr->pr_mtx);
+ osd_jail_set_reserved(pr, mac_do_osd_jail_slot, rsv, nrules);
+ TAILQ_INIT(&nrules->head);
+ mtx_unlock(&ppr->pr_mtx);
+done:
+ if (lrp != NULL)
+ *lrp = rules;
+ else
+ mtx_unlock(&pr->pr_mtx);
+}
+
+static void
+mac_do_dealloc_prison(void *data)
+{
+ struct mac_do_rule *r = data;
+ toast_rules(&r->head);
+}
+
+static int
+mac_do_prison_set(void *obj, void *data)
+{
+ struct prison *pr = obj;
+ struct vfsoptlist *opts = data;
+ struct rulehead head, saved_head;
+ struct mac_do_rule *rules;
+ char *rules_string, *copy_string;
+ int error, jsys, len;
+
+ error = vfs_copyopt(opts, "mdo", &jsys, sizeof(jsys));
+ if (error == ENOENT)
+ jsys = -1;
+ error = vfs_getopt(opts, "mdo.rules", (void **)&rules_string, &len);
+ if (error == ENOENT)
+ rules = NULL;
+ else
+ jsys = JAIL_SYS_NEW;
+ switch (jsys) {
+ case JAIL_SYS_INHERIT:
+ mtx_lock(&pr->pr_mtx);
+ osd_jail_del(pr, mac_do_osd_jail_slot);
+ mtx_unlock(&pr->pr_mtx);
+ break;
+ case JAIL_SYS_NEW:
+ mac_do_alloc_prison(pr, &rules);
+ mtx_unlock(&pr->pr_mtx);
+ if (rules_string == NULL)
+ break;
+ copy_string = strdup(rules_string, M_DO);
+ TAILQ_INIT(&head);
+ error = parse_rules(copy_string, &head);
+ free(copy_string, M_DO);
+ if (error)
+ return (1);
+ TAILQ_INIT(&saved_head);
+ mtx_lock(&pr->pr_mtx);
+ TAILQ_CONCAT(&saved_head, &rules->head, r_entries);
+ TAILQ_CONCAT(&(rules->head), &head, r_entries);
+ strlcpy(rules->string, rules_string, MAC_RULE_STRING_LEN);
+ mtx_unlock(&pr->pr_mtx);
+ toast_rules(&saved_head);
+ break;
+ }
+ return (0);
+}
+
+SYSCTL_JAIL_PARAM_SYS_NODE(mdo, CTLFLAG_RW, "Jail MAC/do parameters");
+SYSCTL_JAIL_PARAM_STRING(_mdo, rules, CTLFLAG_RW, MAC_RULE_STRING_LEN,
+ "Jail MAC/do rules");
+
+static int
+mac_do_prison_get(void *obj, void *data)
+{
+ struct prison *ppr, *pr = obj;
+ struct vfsoptlist *opts = data;
+ struct mac_do_rule *rules;
+ int jsys, error;
+
+ rules = mac_do_rule_find(pr, &ppr);
+ error = vfs_setopt(opts, "mdo", &jsys, sizeof(jsys));
+ if (error != 0 && error != ENOENT)
+ goto done;
+ error = vfs_setopts(opts, "mdo.rules", rules->string);
+ if (error != 0 && error != ENOENT)
+ goto done;
+ mtx_unlock(&ppr->pr_mtx);
+ error = 0;
+done:
+ return (0);
+}
+
+static int
+mac_do_prison_create(void *obj, void *data __unused)
+{
+ struct prison *pr = obj;
+ mac_do_alloc_prison(pr, NULL);
+ return (0);
+}
+
+static int
+mac_do_prison_remove(void *obj, void *data __unused)
+{
+ struct prison *pr = obj;
+ struct mac_do_rule *r;
+ mtx_lock(&pr->pr_mtx);
+ r = osd_jail_get(pr, mac_do_osd_jail_slot);
+ mtx_unlock(&pr->pr_mtx);
+ toast_rules(&r->head);
+ return (0);
+}
+
+static int
+mac_do_prison_check(void *obj, void *data)
+{
+ struct vfsoptlist *opts = data;
+ char *rules_string;
+ int error, jsys, len;
+
+ error = vfs_copyopt(opts, "mdo", &jsys, sizeof(jsys));
+ if (error != ENOENT) {
+ if (error != 0)
+ return (error);
+ if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT)
+ return (EINVAL);
+ }
+ error = vfs_getopt(opts, "mdo.rules", (void **)&rules_string, &len);
+ if (error != ENOENT) {
+ if (error != 0)
+ return (error);
+ if (len > MAC_RULE_STRING_LEN) {
+ vfs_opterror(opts, "mdo.rules too long");
+ return (ENAMETOOLONG);
+ }
+ }
+ if (error == ENOENT)
+ error = 0;
+ return (error);
+}
+
+static void
+init(struct mac_policy_conf *mpc)
+{
+ struct prison *pr;
+ osd_method_t methods[PR_MAXMETHOD] = {
+ [PR_METHOD_CREATE] = mac_do_prison_create,
+ [PR_METHOD_GET] = mac_do_prison_get,
+ [PR_METHOD_SET] = mac_do_prison_set,
+ [PR_METHOD_CHECK] = mac_do_prison_check,
+ [PR_METHOD_REMOVE] = mac_do_prison_remove,
+ };
+
+ mac_do_osd_jail_slot = osd_jail_register(mac_do_dealloc_prison, methods);
+ TAILQ_INIT(&rules0.head);
+ rules0.string[0] = '\0';
+ sx_slock(&allprison_lock);
+ TAILQ_FOREACH(pr, &allprison, pr_list)
+ mac_do_alloc_prison(pr, NULL);
+ sx_sunlock(&allprison_lock);
+}
+
+static bool
+rule_is_valid(struct ucred *cred, struct rule *r)
+{
+ if (r->from_type == RULE_UID && r->f_uid == cred->cr_uid)
+ return (true);
+ if (r->from_type == RULE_GID && r->f_gid == cred->cr_gid)
+ return (true);
+ return (false);
+}
+
+static int
+priv_grant(struct ucred *cred, int priv)
+{
+ struct rule *r;
+ struct prison *pr;
+ struct mac_do_rule *rule;
+
+ if (do_enabled == 0)
+ return (EPERM);
+
+ rule = mac_do_rule_find(cred->cr_prison, &pr);
+ TAILQ_FOREACH(r, &rule->head, r_entries) {
+ if (rule_is_valid(cred, r)) {
+ switch (priv) {
+ case PRIV_CRED_SETGROUPS:
+ case PRIV_CRED_SETUID:
+ mtx_unlock(&pr->pr_mtx);
+ return (0);
+ default:
+ break;
+ }
+ }
+ }
+ mtx_unlock(&pr->pr_mtx);
+ return (EPERM);
+}
+
+static int
+check_setgroups(struct ucred *cred, int ngrp, gid_t *groups)
+{
+ struct rule *r;
+ char *fullpath = NULL;
+ char *freebuf = NULL;
+ struct prison *pr;
+ struct mac_do_rule *rule;
+
+ if (do_enabled == 0)
+ return (0);
+ if (cred->cr_uid == 0)
+ return (0);
+
+ if (vn_fullpath(curproc->p_textvp, &fullpath, &freebuf) != 0)
+ return (EPERM);
+ if (strcmp(fullpath, "/usr/bin/mdo") != 0) {
+ free(freebuf, M_TEMP);
+ return (EPERM);
+ }
+ free(freebuf, M_TEMP);
+
+ rule = mac_do_rule_find(cred->cr_prison, &pr);
+ TAILQ_FOREACH(r, &rule->head, r_entries) {
+ if (rule_is_valid(cred, r)) {
+ mtx_unlock(&pr->pr_mtx);
+ return (0);
+ }
+ }
+ mtx_unlock(&pr->pr_mtx);
+
+ return (EPERM);
+}
+
+static int
+check_setuid(struct ucred *cred, uid_t uid)
+{
+ struct rule *r;
+ int error;
+ char *fullpath = NULL;
+ char *freebuf = NULL;
+ struct prison *pr;
+ struct mac_do_rule *rule;
+
+ if (do_enabled == 0)
+ return (0);
+ if (cred->cr_uid == uid || cred->cr_uid == 0)
+ return (0);
+
+ if (vn_fullpath(curproc->p_textvp, &fullpath, &freebuf) != 0)
+ return (EPERM);
+ if (strcmp(fullpath, "/usr/bin/mdo") != 0) {
+ free(freebuf, M_TEMP);
+ return (EPERM);
+ }
+ free(freebuf, M_TEMP);
+
+ error = EPERM;
+ rule = mac_do_rule_find(cred->cr_prison, &pr);
+ TAILQ_FOREACH(r, &rule->head, r_entries) {
+ if (r->from_type == RULE_UID) {
+ if (cred->cr_uid != r->f_uid)
+ continue;
+ if (r->to_type == RULE_ANY) {
+ error = 0;
+ break;
+ }
+ if (r->to_type == RULE_UID && uid == r->t_uid) {
+ error = 0;
+ break;
+ }
+ }
+ if (r->from_type == RULE_GID) {
+ if (cred->cr_gid != r->f_gid)
+ continue;
+ if (r->to_type == RULE_ANY) {
+ error = 0;
+ break;
+ }
+ if (r->to_type == RULE_UID && uid == r->t_uid) {
+ error = 0;
+ break;
+ }
+ }
+ }
+ mtx_unlock(&pr->pr_mtx);
+ return (error);
+}
+
+static struct mac_policy_ops do_ops =
+{
+ .mpo_destroy = destroy,
+ .mpo_init = init,
+ .mpo_cred_check_setuid = check_setuid,
+ .mpo_cred_check_setgroups = check_setgroups,
+ .mpo_priv_grant = priv_grant,
+};
+
+MAC_POLICY_SET(&do_ops, mac_do, "MAC/do",
+ MPC_LOADTIME_FLAG_UNLOADOK, NULL);
+MODULE_VERSION(mac_do, 1);
diff --git a/usr.bin/Makefile b/usr.bin/Makefile
--- a/usr.bin/Makefile
+++ b/usr.bin/Makefile
@@ -87,6 +87,7 @@
lzmainfo \
m4 \
mandoc \
+ mdo \
mesg \
ministat \
mkdep \
diff --git a/usr.bin/mdo/Makefile b/usr.bin/mdo/Makefile
new file mode 100644
--- /dev/null
+++ b/usr.bin/mdo/Makefile
@@ -0,0 +1,4 @@
+PROG= mdo
+SRCS= mdo.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mdo/mdo.1 b/usr.bin/mdo/mdo.1
new file mode 100644
--- /dev/null
+++ b/usr.bin/mdo/mdo.1
@@ -0,0 +1,42 @@
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright(c) 2024 Baptiste Daroussin <bapt@FreeBSD.org>
+.Dd May 9, 2024
+.Dt MDO 1
+.Os
+.Sh NAME
+.Nm mdo
+.Nd execute commands as another user
+.Sh SYNOPSIS
+.Nm
+.Op Fl u Ar username
+.Op Fl i
+.Op command Op args
+.Sh DESCRIPTION
+The
+.Nm
+utility executes the specified
+.Ar command
+as user
+.Ar username .
+.Pp
+If no
+.Ar username
+is provided it defaults to the
+.Va root
+user.
+If no
+.Ar command
+is specified, it will execute the shell specified as
+.Va SHELL
+environnement variable, falling back on
+.Pa /bin/sh .
+.Pp
+The
+.Fl i
+option can be used to only call
+.Fn setuid
+and keep the group from the calling user.
+.Sh SEE ALSO
+.Xr su 1
+.Xr mac_do 4
diff --git a/usr.bin/mdo/mdo.c b/usr.bin/mdo/mdo.c
new file mode 100644
--- /dev/null
+++ b/usr.bin/mdo/mdo.c
@@ -0,0 +1,76 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright(c) 2024 Baptiste Daroussin <bapt@FreeBSD.org
+ */
+
+#include <sys/limits.h>
+
+#include <err.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: mdo [-u username] [-i] [--] [command [args]]\n");
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct passwd *pw;
+ const char *username = "root";
+ bool uidonly = false;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "u:i")) != -1) {
+ switch (ch) {
+ case 'u':
+ username = optarg;
+ break;
+ case 'i':
+ uidonly = true;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((pw = getpwnam(username)) == NULL) {
+ if (strspn(username, "0123456789") == strlen(username)) {
+ const char *errp = NULL;
+ uid_t uid = strtonum(username, 0, UID_MAX, &errp);
+ if (errp != NULL)
+ err(EXIT_FAILURE, "%s", errp);
+ pw = getpwuid(uid);
+ }
+ if (pw == NULL)
+ err(EXIT_FAILURE, "Invalid username '%s'", username);
+ }
+ if (!uidonly) {
+ if (initgroups(pw->pw_name, pw->pw_gid) == -1)
+ err(EXIT_FAILURE, "Impossible to call initgroups");
+ if (setgid(pw->pw_gid) == -1)
+ err(EXIT_FAILURE, "Impossible to call setgid");
+ }
+ if (setuid(pw->pw_uid) == -1)
+ err(EXIT_FAILURE, "Impossible to call setuid");
+ if (*argv == NULL) {
+ const char *sh = getenv("SHELL");
+ if (sh == NULL)
+ sh = _PATH_BSHELL;
+ execlp(sh, sh, "-i", NULL);
+ } else {
+ execvp(argv[0], argv);
+ }
+ err(EXIT_FAILURE, "exec failed");
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jan 27, 6:13 PM (6 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16203420
Default Alt Text
D45145.id138588.diff (17 KB)
Attached To
Mode
D45145: mac_do: add a new MAC/do policy and mdo(1) utility
Attached
Detach File
Event Timeline
Log In to Comment