summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/Makefile1
-rw-r--r--usr/src/cmd/auditrecord/audit_record_attr.txt11
-rw-r--r--usr/src/cmd/auths/auths.c314
-rw-r--r--usr/src/cmd/csh/i386/Makefile28
-rw-r--r--usr/src/cmd/csh/sh.c94
-rw-r--r--usr/src/cmd/csh/sh.exec.c37
-rw-r--r--usr/src/cmd/csh/sparc/Makefile26
-rw-r--r--usr/src/cmd/fs.d/ufs/newfs/newfs.c5
-rw-r--r--usr/src/cmd/ksh/Makefile10
-rw-r--r--usr/src/cmd/ksh/Makefile.com5
-rw-r--r--usr/src/cmd/perl/contrib/Sun/Solaris/Privilege/Privilege.pm8
-rw-r--r--usr/src/cmd/pfexec/Makefile24
-rw-r--r--usr/src/cmd/pfexec/pfexec.c637
-rw-r--r--usr/src/cmd/pfexecd/Makefile62
-rw-r--r--usr/src/cmd/pfexecd/pfexecd.c525
-rw-r--r--usr/src/cmd/pfexecd/pfexecd.xml86
-rw-r--r--usr/src/cmd/profiles/profiles.c173
-rw-r--r--usr/src/cmd/ptools/ppriv/ppriv.c21
-rw-r--r--usr/src/cmd/sh/Makefile9
-rw-r--r--usr/src/cmd/sh/main.c34
-rw-r--r--usr/src/cmd/sh/service.c40
-rw-r--r--usr/src/cmd/sh/sh_policy.c198
-rw-r--r--usr/src/cmd/sh/sh_policy.h65
-rw-r--r--usr/src/cmd/svc/configd/rc_node.c128
-rw-r--r--usr/src/cmd/truss/actions.c5
-rw-r--r--usr/src/cmd/truss/main.c48
-rw-r--r--usr/src/cmd/truss/print.c4
-rw-r--r--usr/src/cmd/truss/proto.h5
-rw-r--r--usr/src/cmd/truss/ramdata.c4
-rw-r--r--usr/src/cmd/truss/ramdata.h4
-rw-r--r--usr/src/head/prof_attr.h7
-rw-r--r--usr/src/head/secdb.h13
-rw-r--r--usr/src/lib/libbsm/audit_event.txt4
-rw-r--r--usr/src/lib/libc/port/gen/getusershell.c14
-rw-r--r--usr/src/lib/libc/port/gen/privlib.c9
-rw-r--r--usr/src/lib/libsecdb/common/chkauthattr.c482
-rw-r--r--usr/src/lib/libsecdb/common/getexecattr.c113
-rw-r--r--usr/src/lib/libsecdb/common/getprofattr.c48
-rw-r--r--usr/src/lib/libsecdb/common/mapfile-vers8
-rw-r--r--usr/src/lib/libsecdb/exec_attr.txt20
-rw-r--r--usr/src/lib/libsecdb/help/profiles/Makefile1
-rw-r--r--usr/src/lib/libsecdb/help/profiles/RtReservedProfile.html35
-rw-r--r--usr/src/lib/libsecdb/prof_attr.txt2
-rw-r--r--usr/src/lib/libshell/Makefile.com4
-rw-r--r--usr/src/lib/libshell/amd64/src/cmd/ksh93/FEATURE/options4
-rw-r--r--usr/src/lib/libshell/i386/src/cmd/ksh93/FEATURE/options4
-rw-r--r--usr/src/lib/libshell/sparc/src/cmd/ksh93/FEATURE/options4
-rw-r--r--usr/src/lib/libshell/sparcv9/src/cmd/ksh93/FEATURE/options4
-rw-r--r--usr/src/lib/pam_modules/unix_cred/unix_cred.c68
-rw-r--r--usr/src/pkg/manifests/SUNWcs.mf33
-rw-r--r--usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf1
-rw-r--r--usr/src/pkg/manifests/shell-ksh88.mf8
-rw-r--r--usr/src/uts/common/c2/audit.c58
-rw-r--r--usr/src/uts/common/c2/audit.h2
-rw-r--r--usr/src/uts/common/c2/audit_kernel.h12
-rw-r--r--usr/src/uts/common/c2/audit_kevents.h6
-rw-r--r--usr/src/uts/common/c2/audit_start.c8
-rw-r--r--usr/src/uts/common/fs/autofs/auto_vfsops.c6
-rw-r--r--usr/src/uts/common/fs/autofs/auto_vnops.c6
-rw-r--r--usr/src/uts/common/fs/cachefs/cachefs_vnops.c20
-rw-r--r--usr/src/uts/common/fs/dev/sdev_vnops.c10
-rw-r--r--usr/src/uts/common/fs/devfs/devfs_vnops.c12
-rw-r--r--usr/src/uts/common/fs/hsfs/hsfs_node.c11
-rw-r--r--usr/src/uts/common/fs/namefs/namevfs.c7
-rw-r--r--usr/src/uts/common/fs/namefs/namevno.c14
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_vnops.c10
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c10
-rw-r--r--usr/src/uts/common/fs/tmpfs/tmp_subr.c19
-rw-r--r--usr/src/uts/common/fs/udfs/udf_inode.c8
-rw-r--r--usr/src/uts/common/fs/ufs/ufs_inode.c11
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_acl.c75
-rw-r--r--usr/src/uts/common/inet/ip/icmp.c2
-rw-r--r--usr/src/uts/common/inet/ip/spdsock.c31
-rw-r--r--usr/src/uts/common/inet/spdsock.h4
-rw-r--r--usr/src/uts/common/os/cred.c7
-rw-r--r--usr/src/uts/common/os/exec.c145
-rw-r--r--usr/src/uts/common/os/klpd.c465
-rw-r--r--usr/src/uts/common/os/policy.c240
-rw-r--r--usr/src/uts/common/os/priv_defs11
-rw-r--r--usr/src/uts/common/os/project.c7
-rw-r--r--usr/src/uts/common/os/zone.c12
-rw-r--r--usr/src/uts/common/sys/exec.h5
-rw-r--r--usr/src/uts/common/sys/fs/ufs_acl.h9
-rw-r--r--usr/src/uts/common/sys/klpd.h56
-rw-r--r--usr/src/uts/common/sys/policy.h10
-rw-r--r--usr/src/uts/common/sys/priv.h9
-rw-r--r--usr/src/uts/common/sys/zone.h6
-rw-r--r--usr/src/uts/common/syscall/auditsys.c11
-rw-r--r--usr/src/uts/common/syscall/ppriv.c12
-rw-r--r--usr/src/uts/common/syscall/uid.c12
90 files changed, 2689 insertions, 2167 deletions
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index 333c49f8e4..23dbcf9156 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -292,6 +292,7 @@ COMMON_SUBDIRS= \
pcidr \
pcitool \
pfexec \
+ pfexecd \
pgrep \
picl \
plimit \
diff --git a/usr/src/cmd/auditrecord/audit_record_attr.txt b/usr/src/cmd/auditrecord/audit_record_attr.txt
index c9fd667ba2..24dd6b5791 100644
--- a/usr/src/cmd/auditrecord/audit_record_attr.txt
+++ b/usr/src/cmd/auditrecord/audit_record_attr.txt
@@ -2,8 +2,7 @@
# Two "#" are comments that are copied to audit_record_attr
# other comments are removed.
##
-## Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-## Use is subject to license terms.
+## Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
##
## CDDL HEADER START
##
@@ -705,6 +704,14 @@ label=AUE_EXECVE
# return,failure: No such file or directory,-1
# trailer,86
+label=AUE_PFEXEC
+ format=path1:path2:[privileges]3:[privileges]3:[proc]4:exec_args:[exec_env]5
+ comment=pathname of the executable:
+ comment=pathname of working directory:
+ comment=privileges if the limit or inheritable set are changed:
+ comment=process if ruid, euid, rgid or egid is changed:
+ comment=output if arge policy is set
+
label=AUE_EXIT
format=arg1:[text]2
comment=1, exit status, "exit status":
diff --git a/usr/src/cmd/auths/auths.c b/usr/src/cmd/auths/auths.c
index 82416e0017..98141feb88 100644
--- a/usr/src/cmd/auths/auths.c
+++ b/usr/src/cmd/auths/auths.c
@@ -19,12 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -37,10 +34,6 @@
#include <prof_attr.h>
#include <auth_attr.h>
-
-#define ALL_AUTHS "All"
-#define ALL_SUN_AUTHS "solaris.*"
-
#define EXIT_OK 0
#define EXIT_FATAL 1
#define EXIT_NON_FATAL 2
@@ -49,71 +42,57 @@
#define TEXT_DOMAIN "SYS_TEST"
#endif
-#define PROFLIST_SEP ","
-#define AUTH_SEP ","
-#define MAXAUTHS 4096
+#define INCRAUTHS 512
+typedef struct cbs {
+ int auth_cnt;
+ int auth_max;
+ char **auths;
+} cbs_t;
-static int show_auths(char *, char **, int, int);
-static int list_auths(userattr_t *, char **, int *);
-static void get_default_auths(char *, char **, int *);
-static void getProfiles(char *, char **, int *, char **, int *);
-static void add_auths(char *, char **, int *);
-static void free_auths(char **, int *);
+static int show_auths(char *, int);
+static int add_auth(const char *, void *, void *);
+static void free_auths(cbs_t *);
+static void simplify(cbs_t *);
static char *progname = "auths";
-
int
main(int argc, char *argv[])
{
int status = EXIT_OK;
- char *defauths[MAXAUTHS];
- int defauth_cnt = 0;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
switch (argc) {
case 1:
- get_default_auths(NULL, defauths, &defauth_cnt);
- status = show_auths(NULL, defauths, defauth_cnt, 0);
+ status = show_auths(NULL, 0);
break;
case 2:
- get_default_auths(argv[argc-1], defauths, &defauth_cnt);
- status = show_auths(argv[argc-1], defauths, defauth_cnt, 0);
+ status = show_auths(argv[argc-1], 0);
break;
default:
while (*++argv) {
- get_default_auths(*argv, defauths, &defauth_cnt);
- status = show_auths(*argv, defauths, defauth_cnt, 1);
+ status = show_auths(*argv, 1);
if (status == EXIT_FATAL) {
break;
}
- /* free memory allocated for default authorizations */
- free_auths(defauths, &defauth_cnt);
- (void) printf("\n");
}
break;
}
- /* free memory allocated for default authorizations */
- free_auths(defauths, &defauth_cnt);
status = (status == EXIT_OK) ? status : EXIT_FATAL;
-
return (status);
}
-
static int
-show_auths(char *username, char **defauths, int defauth_cnt, int print_name)
+show_auths(char *username, int print_name)
{
int status = EXIT_OK;
struct passwd *pw;
- userattr_t *user;
- char *userauths[MAXAUTHS];
- int userauth_cnt = 0, old_userauth_cnt;
- int i, j, have_allauths, duplicate;
+ int i;
+ cbs_t cbs = { 0, 0, NULL };
if (username == NULL) {
if ((pw = getpwuid(getuid())) == NULL) {
@@ -130,221 +109,120 @@ show_auths(char *username, char **defauths, int defauth_cnt, int print_name)
return (status);
}
- have_allauths = 0;
- if (username != NULL) {
- /* if ALL_AUTHS is default, don't need to look at other auths */
- for (i = 0; i < defauth_cnt; i++) {
- if (strcmp(defauths[i], ALL_AUTHS) == 0) {
- have_allauths = 1;
- break;
- }
- }
- if (have_allauths) {
- status = EXIT_OK;
- } else if ((user = getusernam(username)) != NULL) {
- status = list_auths(user, userauths, &userauth_cnt);
- /* check if any profiles have ALL_AUTHS */
- for (i = 0; i < userauth_cnt; i++) {
- if (strcmp(userauths[i], ALL_AUTHS) == 0) {
- have_allauths = 1;
- break;
- }
- }
- }
- if ((defauth_cnt + userauth_cnt) == 0) {
- status = EXIT_NON_FATAL;
- }
- }
+ (void) _enum_auths(username, add_auth, NULL, &cbs);
+
+ if (cbs.auth_cnt == 0)
+ status = EXIT_NON_FATAL;
+
if (status == EXIT_NON_FATAL) {
- (void) fprintf(stderr, "%s: %s : ", progname, username);
+ (void) fprintf(stderr, "%s: %s: ", progname, username);
(void) fprintf(stderr, gettext("No authorizations\n"));
} else {
- if (print_name) {
- (void) printf("%s : ", username);
- }
-
- if (have_allauths) {
- (void) printf("%s\n", ALL_SUN_AUTHS);
- } else {
- /*
- * combine the user auths and default auths,
- * and eliminate duplicates from the two
- */
- old_userauth_cnt = userauth_cnt;
- for (i = 0; i < defauth_cnt; i++) {
- duplicate = 0;
- for (j = 0; j < old_userauth_cnt; j++) {
- if (strcmp(userauths[j], defauths[i]) ==
- 0) {
- duplicate = 1;
- break;
- }
- }
- if (!duplicate) {
- userauths[userauth_cnt] =
- strdup(defauths[i]);
- userauth_cnt++;
- }
- }
-
- /* print out the auths */
- for (i = 0; i < (userauth_cnt - 1); i++) {
- (void) printf("%s,", userauths[i]);
- }
-
- /* print out the last entry, without the comma */
- (void) printf("%s\n", userauths[userauth_cnt - 1]);
- }
- }
+ simplify(&cbs);
- /* free memory allocated for authorizations */
- free_auths(userauths, &userauth_cnt);
+ if (print_name)
+ (void) printf("%s: ", username);
- return (status);
-}
+ /* print out the auths */
+ for (i = 0; i < cbs.auth_cnt - 1; i++)
+ (void) printf("%s,", cbs.auths[i]);
+ /* print out the last entry, without the comma */
+ (void) printf("%s\n", cbs.auths[cbs.auth_cnt - 1]);
-static int
-list_auths(userattr_t *user, char **authArray, int *authcnt)
-{
- int status = EXIT_OK;
- char *authlist = NULL;
- char *proflist = NULL;
- char *profArray[MAXPROFS];
- int profcnt = 0;
-
- authlist = kva_match(user->attr, USERATTR_AUTHS_KW);
- if (authlist != NULL) {
- add_auths(authlist, authArray, authcnt);
- }
- if ((proflist = kva_match(user->attr, USERATTR_PROFILES_KW)) == NULL) {
- if (authcnt == 0) {
- status = EXIT_NON_FATAL;
- }
- } else {
- getProfiles(proflist, profArray, &profcnt,
- authArray, authcnt);
- free_proflist(profArray, profcnt);
+ /* free memory allocated for authorizations */
+ free_auths(&cbs);
}
- if (authcnt == 0) {
- status = EXIT_NON_FATAL;
- }
- free_userattr(user);
return (status);
}
-
-static void
-get_default_auths(char *user, char **authArray, int *authcnt)
+/*ARGSUSED*/
+static int
+add_auth(const char *authname, void *ctxt, void *res)
{
- char *auths = NULL;
- char *profs = NULL;
- char *profArray[MAXPROFS];
- int profcnt = 0;
+ cbs_t *cbs = res;
- if (user == NULL) {
- struct passwd *pw;
+ if (cbs->auth_cnt >= cbs->auth_max) {
+ cbs->auth_max += INCRAUTHS;
+ cbs->auths = realloc(cbs->auths,
+ cbs->auth_max * sizeof (char *));
- if ((pw = getpwuid(getuid())) != NULL) {
- user = pw->pw_name;
+ if (cbs->auths == NULL) {
+ (void) fprintf(stderr, "%s: ", progname);
+ (void) fprintf(stderr, gettext("Out of memory\n"));
+ exit(1);
}
}
- if (_get_user_defs(user, &auths, &profs) == 0) {
- if (auths != NULL) {
- add_auths(auths, authArray, authcnt);
- }
+ cbs->auths[cbs->auth_cnt] = strdup(authname);
+ cbs->auth_cnt++;
- /* get authorizations from default profiles */
- if (profs != NULL) {
- getProfiles(profs, profArray, &profcnt,
- authArray, authcnt);
- free_proflist(profArray, profcnt);
- }
- _free_user_defs(auths, profs);
- }
+ return (0);
}
-void
-add_auths(char *auths, char **authArray, int *authcnt)
+static void
+free_auths(cbs_t *cbs)
{
- char *authname, *lasts, *real_authname;
- int i;
+ int i;
- for (authname = (char *)strtok_r(auths, AUTH_SEP, &lasts);
- authname != NULL;
- authname = (char *)strtok_r(NULL, AUTH_SEP, &lasts)) {
+ for (i = 0; i < cbs->auth_cnt; i++)
+ free(cbs->auths[i]);
- if ((strcmp(authname, KV_WILDCARD) == 0) ||
- (strcmp(authname, ALL_SUN_AUTHS) == 0)) {
- real_authname = ALL_AUTHS;
- } else {
- real_authname = authname;
- }
+ free(cbs->auths);
+}
- /* check to see if authorization is already in list */
- for (i = 0; i < *authcnt; i++) {
- if (strcmp(real_authname, authArray[i]) == 0) {
- break; /* already in list */
- }
- }
+/* We have always ignored .grant in auths(1) */
+static boolean_t
+auth_match(const char *pattern, const char *auth)
+{
+ size_t len = strlen(pattern);
- /* not in list, add it in */
- if (i == *authcnt) {
- authArray[i] = strdup(real_authname);
- *authcnt = i + 1;
- }
- }
+ if (pattern[len - 1] != KV_WILDCHAR)
+ return (B_FALSE);
+ return (strncmp(pattern, auth, len - 1) == 0);
}
-static void
-free_auths(char *auths[], int *auth_cnt)
+static int
+mstrptr(const void *a, const void *b)
{
- int i;
+ char *const *ap = a;
+ char *const *bp = b;
- for (i = 0; i < *auth_cnt; i++) {
- free(auths[i]);
- }
- *auth_cnt = 0;
+ return (strcmp(*ap, *bp));
}
+/*
+ * Simplify the returned authorizations: sort and match wildcards;
+ * we're using here that "*" sorts before any other character.
+ */
static void
-getProfiles(char *profiles, char **profArray, int *profcnt,
- char **authArray, int *authcnt)
+simplify(cbs_t *cbs)
{
-
- char *prof;
- char *lasts;
- profattr_t *pa;
- char *auths;
- int i;
-
- for (prof = (char *)strtok_r(profiles, PROFLIST_SEP, &lasts);
- prof != NULL;
- prof = (char *)strtok_r(NULL, PROFLIST_SEP, &lasts)) {
-
- getproflist(prof, profArray, profcnt);
- }
-
- /* get authorizations from list of profiles */
- for (i = 0; i < *profcnt; i++) {
-
- if ((pa = getprofnam(profArray[i])) == NULL) {
- /*
- * this should never happen.
- * unless the database has an undefined profile
- */
- continue;
- }
-
- /* get auths this profile */
- auths = kva_match(pa->attr, PROFATTR_AUTHS_KW);
- if (auths != NULL) {
- add_auths(auths, authArray, authcnt);
+ int rem, i;
+
+ /* First we sort */
+ qsort(cbs->auths, cbs->auth_cnt, sizeof (cbs->auths[0]), mstrptr);
+
+ /*
+ * Then we remove the entries which match a later entry.
+ * We walk the list, with "i + rem + 1" the cursor for the possible
+ * candidate for removal. With "rem" we count the removed entries
+ * and we copy while we're looking for duplicate/superfluous entries.
+ */
+ for (i = 0, rem = 0; i < cbs->auth_cnt - rem - 1; ) {
+ if (strcmp(cbs->auths[i], cbs->auths[i + rem + 1]) == 0 ||
+ strchr(cbs->auths[i], KV_WILDCHAR) != NULL &&
+ auth_match(cbs->auths[i], cbs->auths[i + rem + 1])) {
+ free(cbs->auths[i + rem + 1]);
+ rem++;
+ } else {
+ i++;
+ if (rem > 0)
+ cbs->auths[i] = cbs->auths[i + rem];
}
-
- free_profattr(pa);
}
+
+ cbs->auth_cnt -= rem;
}
diff --git a/usr/src/cmd/csh/i386/Makefile b/usr/src/cmd/csh/i386/Makefile
index c580f9f0b4..36ee788fc0 100644
--- a/usr/src/cmd/csh/i386/Makefile
+++ b/usr/src/cmd/csh/i386/Makefile
@@ -1,5 +1,4 @@
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
#
# Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
# All Rights Reserved
@@ -8,8 +7,6 @@
# All rights reserved. The Berkeley Software License Agreement
# specifies the terms and conditions for redistribution.
-# ident "%Z%%M% %I% %E% SMI"
-
#
# C Shell with process control; VM/UNIX VAX Makefile
# Bill Joy UC Berkeley; Jim Kulp IIASA, Austria
@@ -17,8 +14,6 @@
CSH_PROG = csh
PROG = $(CSH_PROG)
-PFCSH_PROG= pfcsh
-ROOTPFCSH= $(ROOTBIN)/$(PFCSH_PROG)
include ../../Makefile.cmd
@@ -27,13 +22,11 @@ DEFS = -DVFORK -DFILEC -DBSD_COMP -DFIVE # No TELL when MBCHAR
CPPFLAGS= -I. $(DEFS) $(MBCHAR) $(CPPFLAGS.master)
CPPFLAGS += -I../../sh
CPPFLAGS += -D_FILE_OFFSET_BITS=64
-LDLIBS += -lcurses -lsecdb
+LDLIBS += -lcurses
MAPFILES = ../mapfile-intf $(MAPFILE.NGB)
LDFLAGS += $(MAPFILES:%=-M%)
-PFOBJS = sh_policy.o
-
HDDEP = sh.o sh.dir.o sh.dol.o sh.err.o sh.exec.o sh.exp.o sh.file.o \
sh.func.o sh.glob.o sh.hist.o sh.init.o sh.lex.o sh.misc.o \
sh.parse.o sh.proc.o sh.sem.o sh.set.o sh.time.o
@@ -42,12 +35,11 @@ COMMONOBJS= printf.o sh.char.o sh.dir.o sh.dol.o sh.err.o \
sh.exec.o sh.exp.o sh.file.o sh.func.o sh.glob.o sh.hist.o sh.init.o \
sh.lex.o sh.misc.o sh.parse.o sh.print.o sh.proc.o sh.sem.o sh.set.o \
sh.time.o sh.tchar.o sh.tconst.o sh.o \
- wait3.o
+ wait3.o
LOCALOBJS= signal.o
COMMONSRCS= $(COMMONOBJS:%.o=../%.c)
-PFSRCS= $(PFOBJS:%=pfcsh_objs/%)
.KEEP_STATE:
@@ -64,23 +56,19 @@ all: $(PROG)
$(COMPILE.c) $<
$(POST_PROCESS_O)
-$(CSH_PROG): $(COMMONOBJS) $(PFOBJS) $(LOCALOBJS) $(MAPFILES)
- $(LINK.c) $(COMMONOBJS) $(PFOBJS) $(LOCALOBJS) -o $@ $(LDLIBS)
+$(CSH_PROG): $(COMMONOBJS) $(LOCALOBJS) $(MAPFILES)
+ $(LINK.c) $(COMMONOBJS) $(LOCALOBJS) -o $@ $(LDLIBS)
$(POST_PROCESS)
-$(ROOTPFCSH): $(ROOTPROG)
- $(RM) $@
- $(LN) $(ROOTPROG) $@
-
$(HDDEP): ../sh.tconst.h
-install: all $(ROOTBINPROG) $(ROOTPROG) $(ROOTPFCSH)
+install: all $(ROOTBINPROG) $(ROOTPROG)
lint: ../sh.tconst.h
- $(LINT.c) $(COMMONSRCS) $(PFSRCS) signal.c
+ $(LINT.c) $(COMMONSRCS) signal.c $(LDLIBS)
clean:
- $(RM) $(LOCALOBJS) $(COMMONOBJS) $(PFOBJS)
+ $(RM) $(LOCALOBJS) $(COMMONOBJS)
clobber: clean
$(RM) $(PROG)
diff --git a/usr/src/cmd/csh/sh.c b/usr/src/cmd/csh/sh.c
index da000b4c14..631a75d39d 100644
--- a/usr/src/cmd/csh/sh.c
+++ b/usr/src/cmd/csh/sh.c
@@ -1,6 +1,5 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -12,8 +11,6 @@
* specifies the terms and conditions for redistribution.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <locale.h>
#include "sh.h"
/* #include <sys/ioctl.h> */
@@ -22,7 +19,6 @@
#include "sh.tconst.h"
#include <pwd.h>
#include <stdlib.h>
-#include "sh_policy.h" /* for pfcsh */
#ifdef TRACE
#include <stdio.h>
#endif
@@ -38,7 +34,8 @@
tchar *pathlist[] = { S_usrbin /* "/usr/bin" */, S_DOT /* "." */, 0 };
tchar *dumphist[] = { S_history /* "history" */, S_h /* "-h" */, 0, 0 };
-tchar *loadhist[] = { S_source /* "source" */, S_h /* "-h" */, S_NDOThistory /* "~/.history" */, 0 };
+tchar *loadhist[] = { S_source /* "source" */, S_h /* "-h" */,
+ S_NDOThistory /* "~/.history" */, 0 };
tchar HIST = '!';
tchar HISTSUB = '^';
int nofile;
@@ -76,7 +73,6 @@ void initdesc(int, char *[]);
void initdesc_x(int, char *[], int);
void closem(void);
void unsetfd(int);
-void secpolicy_print(int, const char *);
void phup(void);
#ifdef TRACE
@@ -119,7 +115,7 @@ tprintf(fmt, a, b, c, d, e, f, g, h, i, j)
int
main(int c, char **av)
{
- tchar **v, *cp, *p, *q, *r;
+ tchar **v, *cp, *r;
int f;
struct sigvec osv;
struct sigaction sa;
@@ -127,8 +123,6 @@ main(int c, char **av)
char *c_max_var_len;
int c_max_var_len_size;
- pfcshflag = 0;
-
/*
* set up the error exit, if there is an error before
* this is done, it will core dump, and we don't
@@ -153,29 +147,6 @@ main(int c, char **av)
#endif
(void) textdomain(TEXT_DOMAIN);
- /*
- * This is a profile shell if the simple name of argv[0] is
- * pfcsh or -pfcsh
- */
- p = strtots(NOSTR, "pfcsh");
- r = strtots(NOSTR, "-pfcsh");
- if ((p != NOSTR) && (r != NOSTR) &&
- ((q = strtots(NOSTR, *av)) != NOSTR)) {
- if (c > 0 && (eq(p, simple(q)) || eq(r, simple(q)))) {
- pfcshflag = 1;
- }
- xfree(q);
- }
-
- if (p != NOSTR)
- xfree(p);
- if (r != NOSTR)
- xfree(r);
-
- if (pfcshflag == 1) {
- secpolicy_init();
- }
-
/* Copy arguments */
v = strblktotsblk(av, c);
@@ -250,8 +221,7 @@ main(int c, char **av)
if (pw != NULL) {
set(S_user, strtots((tchar *)0, pw->pw_name));
local_setenv(S_USER, strtots((tchar *)0, pw->pw_name));
- }
- else if (loginsh) { /* Give up setting USER variable. */
+ } else if (loginsh) { /* Give up setting USER variable. */
printf("Warning: USER environment variable could not be set.\n");
}
}
@@ -428,7 +398,8 @@ main(int c, char **av)
*/
if (prompt) {
gethostname_(s_prompt, MAXHOSTNAMELEN);
- strcat_(s_prompt, uid == 0 ? S_SHARPSP /* "# " */ : S_PERSENTSP /* "% " */);
+ strcat_(s_prompt,
+ uid == 0 ? S_SHARPSP /* "# " */ : S_PERSENTSP /* "% " */);
set(S_prompt /* "prompt" */, s_prompt);
}
@@ -478,7 +449,8 @@ retry:
if (ioctl(f, TIOCGPGRP, (char *)&tpgrp) == 0 &&
tpgrp != -1) {
if (tpgrp != shpgrp) {
- void (*old)() = (void (*)())signal(SIGTTIN, SIG_DFL);
+ void (*old)() = (void (*)())
+ signal(SIGTTIN, SIG_DFL);
(void) kill(0, SIGTTIN);
(void) signal(SIGTTIN, old);
goto retry;
@@ -530,7 +502,8 @@ printf("Warning: no access to tty; thus no job control in this shell...\n");
}
/* Will have value("home") here because set fast if don't */
- srccat(value(S_home /* "home" */), S_SLADOTcshrc /* "/.cshrc" */);
+ srccat(value(S_home /* "home" */),
+ S_SLADOTcshrc /* "/.cshrc" */);
/* Hash path */
if (!fast && !arginp && !onelflg && !havhash)
@@ -543,7 +516,8 @@ printf("Warning: no access to tty; thus no job control in this shell...\n");
*/
dosource(loadhist);
if (loginsh) {
- srccat_inlogin(value(S_home /* "home" */), S_SLADOTlogin /* "/.login" */);
+ srccat_inlogin(value(S_home /* "home" */),
+ S_SLADOTlogin /* "/.login" */);
}
/*
@@ -726,7 +700,7 @@ srcunit(int unit, bool onlyown, bool hflg)
reenter++;
if (reenter == 1) {
/* Setup the new values of the state stuff saved above */
- copy((char *)&saveB, (char *)&B, sizeof saveB);
+ copy((char *)&saveB, (char *)&B, sizeof (saveB));
fbuf = (tchar **) 0;
fseekp = feobp = fblocks = 0;
oSHIN = SHIN, SHIN = unit, arginp = 0, onelflg = 0;
@@ -758,7 +732,7 @@ srcunit(int unit, bool onlyown, bool hflg)
xfree((char *)fbuf);
/* Reset input arena */
- copy((char *)&B, (char *)&saveB, sizeof B);
+ copy((char *)&B, (char *)&saveB, sizeof (B));
(void) close(SHIN), SHIN = oSHIN;
unsetfd(SHIN);
@@ -819,7 +793,8 @@ goodbye(void)
(void) signal(SIGTERM, SIG_IGN);
setintr = 0; /* No interrupts after "logout" */
if (adrof(S_home /* "home" */))
- srccat(value(S_home /* "home" */), S_SLADOTlogout /* "/.logout" */);
+ srccat(value(S_home /* "home" */),
+ S_SLADOTlogout /* "/.logout" */);
}
rechist();
exitstat();
@@ -1215,7 +1190,7 @@ tchar **
strblktotsblk(char **v, int num)
{
tchar **newv =
- (tchar **)xcalloc((unsigned)(num+ 1), sizeof (tchar **));
+ (tchar **)xcalloc((unsigned)(num+ 1), sizeof (tchar **));
tchar **onewv = newv;
while (*v && num--)
@@ -1332,15 +1307,15 @@ initdesc_x(int argc, char *argv[], int is_reinit)
* in the form /dev/fd/X.
*/
if (argc >= 3)
- if (sscanf(argv[2], "/dev/fd/%d", &script_fd) != 1)
- script_fd = -1;
- else
- fcntl(script_fd, F_SETFD, 1); /* Make sure to close
- * this file on exec.
- */
+ if (sscanf(argv[2], "/dev/fd/%d", &script_fd) != 1)
+ script_fd = -1;
+ else
+ /* Make sure to close this file on exec. */
+ fcntl(script_fd, F_SETFD, 1);
if (fdinuse == NULL) {
- nbytesused = sizeof (int) * howmany(NoFile, sizeof (int) * NBBY);
+ nbytesused = sizeof (int) *
+ howmany(NoFile, sizeof (int) * NBBY);
fdinuse = (int *)xalloc(nbytesused);
}
@@ -1474,22 +1449,3 @@ unsetfd(int fd)
max_fd = 0;
}
}
-
-/*
- * A generic call back routine to output error messages from the
- * policy backing functions called by pfcsh.
- */
-void
-secpolicy_print(int level, const char *msg)
-{
- switch (level) {
- case SECPOLICY_WARN:
- default:
- haderr = 1;
- printf("%s: ", msg); /* printf() does gettext() */
- break;
- case SECPOLICY_ERROR:
- bferr((char *)msg); /* bferr() does gettext() */
- break;
- }
-}
diff --git a/usr/src/cmd/csh/sh.exec.c b/usr/src/cmd/csh/sh.exec.c
index e80bfec8dc..eee2d16440 100644
--- a/usr/src/cmd/csh/sh.exec.c
+++ b/usr/src/cmd/csh/sh.exec.c
@@ -1,6 +1,5 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -12,13 +11,10 @@
* specifies the terms and conditions for redistribution.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "sh.h"
#include <dirent.h>
#include <string.h>
#include "sh.tconst.h"
-#include "sh_policy.h"
/*
@@ -123,7 +119,8 @@ doexec(struct command *t)
pv = justabs;
else
pv = v->vec;
- sav = strspl(S_SLASH /* "/" */, *av); /* / command name for postpending */
+ /* / command name for postpending */
+ sav = strspl(S_SLASH /* "/" */, *av);
#ifdef VFORK
Vsav = sav;
#endif
@@ -140,7 +137,8 @@ doexec(struct command *t)
goto cont;
}
- if (pv[0][0] == 0 || eq(pv[0], S_DOT /* "." */)) { /* don't make ./xxx */
+ /* don't make ./xxx */
+ if (pv[0][0] == 0 || eq(pv[0], S_DOT /* "." */)) {
texec(t, *av, av);
} else {
dp = strspl(*pv, sav);
@@ -193,7 +191,6 @@ pexerr(void)
void
texec(struct command *cmd, tchar *f, tchar **t)
{
- int pfstatus = 0;
struct varent *v;
tchar **vp;
tchar *lastsh[2];
@@ -204,16 +201,7 @@ texec(struct command *cmd, tchar *f, tchar **t)
/* convert cfname and cargs from tchar to char */
tconvert(cmd, f, t);
- if (pfcshflag == 1) {
- pfstatus = secpolicy_pfexec((const char *)(cmd->cfname),
- cmd->cargs, (const char **)NULL);
- if (pfstatus != NOATTRS) {
- errno = pfstatus;
- }
- }
- if ((pfcshflag == 0) || (pfstatus == NOATTRS)) {
- execv(cmd->cfname, cmd->cargs);
- }
+ execv(cmd->cfname, cmd->cargs);
/*
* exec returned, free up allocations from above
@@ -257,7 +245,9 @@ texec(struct command *cmd, tchar *f, tchar **t)
#endif
vp = lastsh;
- vp[0] = adrof(S_shell /* "shell" */) ? value(S_shell /* "shell" */) : S_SHELLPATH /* SHELLPATH */;
+ vp[0] = adrof(S_shell /* "shell" */) ?
+ value(S_shell /* "shell" */) :
+ S_SHELLPATH /* SHELLPATH */;
vp[1] = (tchar *) NULL;
#ifdef OTHERSH
if (ff != -1 && read_(ff, ch, 1) == 1 && ch[0] != '#')
@@ -314,7 +304,7 @@ tconvert(struct command *cmd, tchar *fname, tchar **list)
len = blklen(list);
rc = cmd->cargs = (char **)
- xcalloc((uint_t)(len + 1), sizeof (char **));
+ xcalloc((uint_t)(len + 1), sizeof (char **));
while (len--)
*rc++ = tstostr(NULL, *list++);
*rc = NULL;
@@ -399,9 +389,7 @@ dohash(char cachearray[])
for (cnt = 0; cnt < (HSHSIZ / 8); cnt++)
cachearray[cnt] = 0;
if (v == 0)
- {
return;
- }
for (pv = v->vec; *pv; pv++, i++) {
if (pv[0][0] != '/')
continue;
@@ -420,7 +408,8 @@ dohash(char cachearray[])
(dp->d_name[1] == '\0' ||
dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
continue;
- hashval = hash(hashname(strtots(curdir_, dp->d_name)), i);
+ hashval = hash(hashname(strtots(curdir_, dp->d_name)),
+ i);
bis(cachearray, hashval);
}
unsetfd(dirp->dd_fd);
@@ -449,7 +438,7 @@ hashstat(void)
if (hits+misses)
printf("%d hits, %d misses, %d%%\n",
- hits, misses, 100 * hits / (hits + misses));
+ hits, misses, 100 * hits / (hits + misses));
}
#endif
diff --git a/usr/src/cmd/csh/sparc/Makefile b/usr/src/cmd/csh/sparc/Makefile
index 8a5bf81e4c..37c536f83e 100644
--- a/usr/src/cmd/csh/sparc/Makefile
+++ b/usr/src/cmd/csh/sparc/Makefile
@@ -1,5 +1,4 @@
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
# All Rights Reserved
@@ -8,8 +7,6 @@
# All rights reserved. The Berkeley Software License Agreement
# specifies the terms and conditions for redistribution.
-# ident "%Z%%M% %I% %E% SMI"
-
#
# C Shell with process control; VM/UNIX VAX Makefile
# Bill Joy UC Berkeley; Jim Kulp IIASA, Austria
@@ -17,8 +14,6 @@
CSH_PROG = csh
PROG = $(CSH_PROG)
-PFCSH_PROG= pfcsh
-ROOTPFCSH= $(ROOTBIN)/$(PFCSH_PROG)
include ../../Makefile.cmd
@@ -27,7 +22,7 @@ DEFS = -DVFORK -DFILEC -DBSD_COMP -DFIVE # No TELL when MBCHAR
CPPFLAGS= -I. $(DEFS) $(MBCHAR) $(CPPFLAGS.master)
CPPFLAGS += -I../../sh
CPPFLAGS += -D_FILE_OFFSET_BITS=64
-LDLIBS += -lcurses -lsecdb
+LDLIBS += -lcurses
MAPFILES = ../mapfile-intf $(MAPFILE.NGB)
LDFLAGS += $(MAPFILES:%=-M%)
@@ -42,12 +37,11 @@ COMMONOBJS= printf.o sh.char.o sh.dir.o sh.dol.o sh.err.o \
sh.exec.o sh.exp.o sh.file.o sh.func.o sh.glob.o sh.hist.o sh.init.o \
sh.lex.o sh.misc.o sh.parse.o sh.print.o sh.proc.o sh.sem.o sh.set.o \
sh.time.o sh.tchar.o sh.tconst.o sh.o \
- wait3.o
+ wait3.o
LOCALOBJS= signal.o
COMMONSRCS= $(COMMONOBJS:%.o=../%.c)
-PFSRCS= ../../sh/sh_policy.c
.KEEP_STATE:
@@ -64,23 +58,19 @@ all: $(PROG)
$(COMPILE.c) $<
$(POST_PROCESS_O)
-$(CSH_PROG): $(COMMONOBJS) $(PFOBJS) $(LOCALOBJS) $(MAPFILES)
- $(LINK.c) $(COMMONOBJS) $(PFOBJS) $(LOCALOBJS) -o $@ $(LDLIBS)
+$(CSH_PROG): $(COMMONOBJS) $(LOCALOBJS) $(MAPFILES)
+ $(LINK.c) $(COMMONOBJS) $(LOCALOBJS) -o $@ $(LDLIBS)
$(POST_PROCESS)
-$(ROOTPFCSH): $(ROOTPROG)
- $(RM) $@
- $(LN) $(ROOTPROG) $@
-
$(HDDEP): ../sh.tconst.h
-install: all $(ROOTBINPROG) $(ROOTPROG) $(ROOTPFCSH)
+install: all $(ROOTBINPROG) $(ROOTPROG)
lint: ../sh.tconst.h
- $(LINT.c) $(COMMONSRCS) $(PFSRCS) signal.c $(LDLIBS)
+ $(LINT.c) $(COMMONSRCS) signal.c $(LDLIBS)
clean:
- $(RM) $(LOCALOBJS) $(COMMONOBJS) $(PFOBJS)
+ $(RM) $(LOCALOBJS) $(COMMONOBJS)
clobber: clean
$(RM) $(PROG)
diff --git a/usr/src/cmd/fs.d/ufs/newfs/newfs.c b/usr/src/cmd/fs.d/ufs/newfs/newfs.c
index d517971873..a59b8584f1 100644
--- a/usr/src/cmd/fs.d/ufs/newfs/newfs.c
+++ b/usr/src/cmd/fs.d/ufs/newfs/newfs.c
@@ -22,8 +22,7 @@
/*
* newfs: friendly front end to mkfs
*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/param.h>
@@ -622,7 +621,7 @@ main(int argc, char *argv[])
* If alternates-per-cylinder is ever implemented:
* need to get apc from dp->d_apc if no -a switch???
*/
- (void) snprintf(cmd, sizeof (cmd), "pfexec mkfs -F ufs "
+ (void) snprintf(cmd, sizeof (cmd), "mkfs -F ufs "
"%s%s%s%s %lld %d %d %d %d %d %d %d %d %s %d %d %d %d %s",
Nflag ? "-o N " : "", binary_sb ? "-o calcbinsb " : "",
text_sb ? "-o calcsb " : "", special,
diff --git a/usr/src/cmd/ksh/Makefile b/usr/src/cmd/ksh/Makefile
index bc4e80bd43..a2eb19cde9 100644
--- a/usr/src/cmd/ksh/Makefile
+++ b/usr/src/cmd/ksh/Makefile
@@ -20,16 +20,14 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
SHELL=/usr/bin/ksh93
PROG= ksh
-USRKSH_ALIAS_LIST=ksh ksh93 rksh rksh93 pfksh pfksh93 pfrksh pfrksh93
-
+USRKSH_ALIAS_LIST=ksh ksh93 rksh rksh93
include ../Makefile.cmd
@@ -82,10 +80,6 @@ install: $(ISAEXEC) $(SUBDIRS)
$(SYMLINK) ../usr/bin/ksh93 $(ROOTSBIN)/jsh
$(RM) $(ROOTBIN)/jsh
$(SYMLINK) ksh93 $(ROOTBIN)/jsh
- $(RM) $(ROOTSBIN)/pfsh
- $(SYMLINK) ../usr/bin/ksh93 $(ROOTSBIN)/pfsh
- $(RM) $(ROOTBIN)/pfsh
- $(SYMLINK) ksh93 $(ROOTBIN)/pfsh
$(RM) $(ROOTBIN)/sh
$(SYMLINK) $(ARCH32)/ksh93 $(ROOTBIN)/sh
$(RM) $(ROOTLIB)/rsh
diff --git a/usr/src/cmd/ksh/Makefile.com b/usr/src/cmd/ksh/Makefile.com
index 519ce850fd..75685dfa18 100644
--- a/usr/src/cmd/ksh/Makefile.com
+++ b/usr/src/cmd/ksh/Makefile.com
@@ -20,15 +20,14 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
SHELL=/usr/bin/ksh93
PROG= ksh
-USRKSH_ALIAS_LIST=ksh ksh93 rksh rksh93 pfksh pfksh93 pfrksh pfrksh93
+USRKSH_ALIAS_LIST=ksh ksh93 rksh rksh93
OBJECTS= \
pmain.o
diff --git a/usr/src/cmd/perl/contrib/Sun/Solaris/Privilege/Privilege.pm b/usr/src/cmd/perl/contrib/Sun/Solaris/Privilege/Privilege.pm
index 10c6cd02b4..0965ef925e 100644
--- a/usr/src/cmd/perl/contrib/Sun/Solaris/Privilege/Privilege.pm
+++ b/usr/src/cmd/perl/contrib/Sun/Solaris/Privilege/Privilege.pm
@@ -19,8 +19,7 @@
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -33,14 +32,15 @@ use warnings;
package Sun::Solaris::Privilege;
-our $VERSION = '1.3';
+our $VERSION = '1.4';
use XSLoader;
XSLoader::load(__PACKAGE__, $VERSION);
our (@EXPORT_OK, %EXPORT_TAGS);
my @constants = qw(PRIV_STR_SHORT PRIV_STR_LIT PRIV_STR_PORT PRIV_ON PRIV_OFF
- PRIV_SET PRIV_AWARE PRIV_AWARE_RESET PRIV_DEBUG);
+ PRIV_SET PRIV_AWARE PRIV_AWARE_RESET PRIV_DEBUG PRIV_PFEXEC
+ PRIV_XPOLICY NET_MAC_AWARE NET_MAC_AWARE_INHERIT __PROC_PROTECT);
my @syscalls = qw(setppriv getppriv setpflags getpflags);
my @libcalls = qw(priv_addset priv_copyset priv_delset
priv_emptyset priv_fillset priv_intersect priv_inverse priv_ineffect
diff --git a/usr/src/cmd/pfexec/Makefile b/usr/src/cmd/pfexec/Makefile
index 4f60f15ddd..08bfd04df6 100644
--- a/usr/src/cmd/pfexec/Makefile
+++ b/usr/src/cmd/pfexec/Makefile
@@ -19,30 +19,38 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
#
PROG= pfexec
SRCS= $(PROG:%=%.c)
PFEXEC= pfexec
+BINSHELLS = bash csh ksh ksh93 rksh rksh93 sh tcsh zsh
+
include ../Makefile.cmd
-FILEMODE = 04555
+FILEMODE = 0555
ROOTBINPFEXEC = $(PFEXEC:%=$(ROOTBIN)/%)
.KEEP_STATE:
-CPPFLAGS += -D_REENTRANT
-LDLIBS += -lsecdb -lbsm
-
all: $(PROG)
install: all $(ROOTBINPFEXEC)
+ for s in $(BINSHELLS); do \
+ $(RM) $(ROOTBIN)/pf$$s; \
+ $(LN) $(ROOTBIN)/pfexec $(ROOTBIN)/pf$$s; \
+ done
+ $(RM) $(ROOTXPG4BIN)/pfsh
+ $(LN) $(ROOTBIN)/pfexec $(ROOTXPG4BIN)/pfsh
+ $(RM) $(ROOTSBIN)/pfsh
+ $(SYMLINK) ../usr/bin/pfexec $(ROOTSBIN)/pfsh
+ $(RM) $(ROOTHASBIN)/pfsh
+ $(LN) $(ROOTBIN)/pfexec $(ROOTHASBIN)/pfsh
+ $(RM) $(ROOTHASBIN)/pfksh
+ $(LN) $(ROOTBIN)/pfexec $(ROOTHASBIN)/pfksh
clean:
diff --git a/usr/src/cmd/pfexec/pfexec.c b/usr/src/cmd/pfexec/pfexec.c
index 206055d431..a0025d26a7 100644
--- a/usr/src/cmd/pfexec/pfexec.c
+++ b/usr/src/cmd/pfexec/pfexec.c
@@ -19,397 +19,68 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
+/*
+ * New implementation of pfexec(1) and all of the profile shells.
+ *
+ * The algorithm is as follows:
+ * first try to derive the shell's path from getexecname();
+ * note that this requires a *hard* link to the program, so
+ * if we find that we are actually executing pfexec, we start
+ * looking at argv[0].
+ * argv[0] is also our fallback in case getexecname doesn't find it.
+ */
+#include <sys/param.h>
+#include <alloca.h>
#include <errno.h>
-#include <deflt.h>
#include <locale.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
+#include <priv.h>
+#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <pwd.h>
-#include <grp.h>
#include <string.h>
-#include <exec_attr.h>
-#include <user_attr.h>
-#include <auth_attr.h>
-#include <prof_attr.h>
-#include <errno.h>
-#include <priv.h>
-
-#include <bsm/adt.h>
-#include <bsm/adt_event.h>
+#include <unistd.h>
-#ifndef TEXT_DOMAIN /* Should be defined by cc -D */
+#define PFEXEC "pfexec"
+#ifndef TEXT_DOMAIN
#define TEXT_DOMAIN "SYS_TEST"
#endif
-extern int cannot_audit(int);
-
-static char *pathsearch(char *);
-static int getrealpath(const char *, char *);
-static int checkattrs(char *, int, char *[]);
-static void sanitize_environ();
-static uid_t get_uid(char *);
-static gid_t get_gid(char *);
-static priv_set_t *get_privset(const char *);
-static priv_set_t *get_granted_privs(uid_t);
-static void get_default_privs(const char *, priv_set_t *);
-static void get_profile_privs(char *, char **, int *, priv_set_t *);
-
-static int isnumber(char *);
-static void usage(void);
-
-extern char **environ;
-
-#define PROFLIST_SEP ","
-
-int
-main(int argc, char *argv[])
-{
- char *cmd;
- char **cmdargs;
- char cmd_realpath[MAXPATHLEN];
- int c;
- char *pset = NULL;
-
- (void) setlocale(LC_ALL, "");
- (void) textdomain(TEXT_DOMAIN);
-
- while ((c = getopt(argc, argv, "P:")) != EOF) {
- switch (c) {
- case 'P':
- if (pset == NULL) {
- pset = optarg;
- break;
- }
- /* FALLTHROUGH */
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc < 1)
- usage();
-
- cmd = argv[0];
- cmdargs = &argv[0];
-
- if (pset != NULL) {
- uid_t uid = getuid();
- priv_set_t *wanted = get_privset(pset);
- priv_set_t *granted;
-
- adt_session_data_t *ah; /* audit session handle */
- adt_event_data_t *event; /* event to be generated */
- char cwd[MAXPATHLEN];
-
- granted = get_granted_privs(uid);
-
- /* Audit use */
- if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
- perror("pfexec: adt_start_session");
- exit(EXIT_FAILURE);
- }
- if ((event = adt_alloc_event(ah, ADT_prof_cmd)) == NULL) {
- perror("pfexec: adt_alloc_event");
- exit(EXIT_FAILURE);
- }
- if ((event->adt_prof_cmd.cwdpath =
- getcwd(cwd, sizeof (cwd))) == NULL) {
- (void) fprintf(stderr,
- gettext("pfexec: can't add cwd path\n"));
- exit(EXIT_FAILURE);
- }
-
- event->adt_prof_cmd.cmdpath = cmd;
- event->adt_prof_cmd.argc = argc - 1;
- event->adt_prof_cmd.argv = &argv[1];
- event->adt_prof_cmd.envp = environ;
-
- if (granted != NULL) {
- priv_intersect(granted, wanted);
- event->adt_prof_cmd.inherit_set = wanted;
- if (adt_put_event(event, ADT_SUCCESS,
- ADT_SUCCESS) != 0) {
- perror("pfexec: adt_put_event");
- exit(EXIT_FAILURE);
- }
- if (setppriv(PRIV_ON, PRIV_INHERITABLE, wanted) != 0) {
- (void) fprintf(stderr,
- gettext("setppriv(): %s\n"),
- strerror(errno));
- exit(EXIT_FAILURE);
- }
- /* Trick exec into thinking we're not suid */
- (void) setppriv(PRIV_ON, PRIV_PERMITTED, wanted);
- priv_freeset(event->adt_prof_cmd.inherit_set);
- } else {
- if (adt_put_event(event, ADT_SUCCESS,
- ADT_SUCCESS) != 0) {
- perror("pfexec: adt_put_event");
- exit(EXIT_FAILURE);
- }
- }
- adt_free_event(event);
- (void) adt_end_session(ah);
- (void) setreuid(uid, uid);
- (void) execvp(cmd, cmdargs);
- (void) fprintf(stderr,
- gettext("pfexec: can't execute %s: %s\n"),
- cmd, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- if ((cmd = pathsearch(cmd)) == NULL)
- exit(EXIT_FAILURE);
-
- if (getrealpath(cmd, cmd_realpath) == 0)
- exit(EXIT_FAILURE);
-
- if (checkattrs(cmd_realpath, argc, argv) == 0)
- exit(EXIT_FAILURE);
-
- (void) execv(cmd, cmdargs);
- /*
- * We'd be here only if execv fails.
- */
- (void) fprintf(stderr, gettext("pfexec: can't execute %s: %s\n"),
- cmd, strerror(errno));
- exit(EXIT_FAILURE);
-/* LINTED */
-}
-
-
-/*
- * gets realpath for cmd.
- * return 1 on success, 0 on failure.
- */
-static int
-getrealpath(const char *cmd, char *cmd_realpath)
-{
- if (realpath(cmd, cmd_realpath) == NULL) {
- (void) fprintf(stderr,
- gettext("pfexec: can't get real path of ``%s''\n"), cmd);
- return (0);
- }
- return (1);
-}
-
-/*
- * gets execution attributed for cmd, sets uids/gids, checks environ.
- * returns 1 on success, 0 on failure.
- */
-static int
-checkattrs(char *cmd_realpath, int argc, char *argv[])
-{
- char *value;
- uid_t uid, euid;
- gid_t gid = (gid_t)-1;
- gid_t egid = (gid_t)-1;
- struct passwd *pwent;
- execattr_t *exec;
- priv_set_t *lset = NULL;
- priv_set_t *iset = NULL;
-
- adt_session_data_t *ah; /* audit session handle */
- adt_event_data_t *event; /* event to be generated */
- char cwd[MAXPATHLEN];
-
- uid = euid = getuid();
- if ((pwent = getpwuid(uid)) == NULL) {
- (void) fprintf(stderr, "%d: ", (int)uid);
- (void) fprintf(stderr, gettext("can't get passwd entry\n"));
- return (0);
- }
- /* Set up to audit use */
- if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
- perror("pfexec: adt_start_session");
- return (0);
- }
- if ((event = adt_alloc_event(ah, ADT_prof_cmd)) == NULL) {
- perror("pfexec: adt_alloc_event");
- return (0);
- }
- if ((event->adt_prof_cmd.cwdpath = getcwd(cwd, sizeof (cwd))) == NULL) {
- (void) fprintf(stderr, gettext("pfexec: can't add cwd path\n"));
- return (0);
- }
- /*
- * Get the exec attrs: uid, gid, euid and egid
- */
- if ((exec = getexecuser(pwent->pw_name,
- KV_COMMAND, (char *)cmd_realpath, GET_ONE)) == NULL) {
- (void) fprintf(stderr, "%s: ", cmd_realpath);
- (void) fprintf(stderr,
- gettext("can't get execution attributes\n"));
- return (0);
- }
- if ((value = kva_match(exec->attr, EXECATTR_UID_KW)) != NULL) {
- euid = uid = get_uid(value);
- event->adt_prof_cmd.proc_euid = uid;
- event->adt_prof_cmd.proc_ruid = uid;
- }
- if ((value = kva_match(exec->attr, EXECATTR_GID_KW)) != NULL) {
- egid = gid = get_gid(value);
- event->adt_prof_cmd.proc_egid = gid;
- event->adt_prof_cmd.proc_rgid = gid;
- }
- if ((value = kva_match(exec->attr, EXECATTR_EUID_KW)) != NULL) {
- event->adt_prof_cmd.proc_euid = euid = get_uid(value);
- }
- if ((value = kva_match(exec->attr, EXECATTR_EGID_KW)) != NULL) {
- event->adt_prof_cmd.proc_egid = egid = get_gid(value);
- }
- if ((value = kva_match(exec->attr, EXECATTR_LPRIV_KW)) != NULL) {
- lset = get_privset(value);
- event->adt_prof_cmd.limit_set = lset;
- }
- if ((value = kva_match(exec->attr, EXECATTR_IPRIV_KW)) != NULL) {
- iset = get_privset(value);
- event->adt_prof_cmd.inherit_set = iset;
- }
- if (euid == uid || iset != NULL) {
- sanitize_environ();
- }
-
- /* Finish audit info */
- event->adt_prof_cmd.cmdpath = cmd_realpath;
- event->adt_prof_cmd.argc = argc - 1;
- event->adt_prof_cmd.argv = &argv[1];
- event->adt_prof_cmd.envp = environ;
- if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
- perror("pfexec: adt_put_event");
- return (0);
- }
- adt_free_event(event);
- (void) adt_end_session(ah);
-
-set_attrs:
- /*
- * Set gids/uids and privileges.
- *
- */
- if ((gid != (gid_t)-1) || (egid != (gid_t)-1)) {
- if ((setregid(gid, egid) == -1)) {
- (void) fprintf(stderr, "%s: ", cmd_realpath);
- (void) fprintf(stderr, gettext("can't set gid\n"));
- return (0);
- }
- }
- if (lset != NULL && setppriv(PRIV_SET, PRIV_LIMIT, lset) != 0 ||
- iset != NULL && setppriv(PRIV_ON, PRIV_INHERITABLE, iset) != 0) {
- (void) fprintf(stderr, gettext("%s: can't set privileges\n"),
- cmd_realpath);
- return (0);
- }
- if (setreuid(uid, euid) == -1) {
- (void) fprintf(stderr, "%s: ", cmd_realpath);
- (void) fprintf(stderr, gettext("can't set uid\n"));
- return (0);
- }
- if (iset != NULL && getppriv(PRIV_INHERITABLE, iset) == 0)
- (void) setppriv(PRIV_SET, PRIV_PERMITTED, iset);
-
- free_execattr(exec);
-
- return (1);
-}
-
+#define RES_PFEXEC 1
+#define RES_OK 0
+#define RES_FAILURE -1
/*
- * cleans up environ. code from su.c
+ * Return the shellname
*/
-static void
-sanitize_environ()
-{
- char **pp = environ;
- char **qq, *p;
-
- while ((p = *pp) != NULL) {
- if (*p == 'L' && p[1] == 'D' && p[2] == '_') {
- for (qq = pp; (*qq = qq[1]) != NULL; qq++) {
- ;
- }
- } else {
- pp++;
- }
- }
-}
-
-
-static uid_t
-get_uid(char *value)
-{
- struct passwd *passwd_ent;
-
- if ((passwd_ent = getpwnam(value)) != NULL)
- return (passwd_ent->pw_uid);
-
- if (isnumber(value))
- return (atoi(value));
-
- (void) fprintf(stderr, "pfexec: %s: ", value);
- (void) fprintf(stderr, gettext("can't get user entry\n"));
- exit(EXIT_FAILURE);
- /*NOTREACHED*/
-}
-
-
-static uid_t
-get_gid(char *value)
+int
+shellname(const char *name, char buf[MAXPATHLEN])
{
- struct group *group_ent;
+ const char *cmd = strrchr(name, '/');
- if ((group_ent = getgrnam(value)) != NULL)
- return (group_ent->gr_gid);
+ if (cmd == NULL)
+ cmd = name;
+ else
+ cmd++;
- if (isnumber(value))
- return (atoi(value));
+ if (strncmp(cmd, "pf", 2) != 0)
+ return (RES_FAILURE);
- (void) fprintf(stderr, "pfexec: %s: ", value);
- (void) fprintf(stderr, gettext("can't get group entry\n"));
- exit(EXIT_FAILURE);
- /*NOTREACHED*/
-}
+ if (strcmp(cmd, PFEXEC) == 0)
+ return (RES_PFEXEC);
+ if (strlen(name) >= MAXPATHLEN)
+ return (RES_FAILURE);
-static int
-isnumber(char *s)
-{
- int c;
-
- if (*s == '\0')
- return (0);
-
- while ((c = *s++) != '\0') {
- if (!isdigit(c)) {
- return (0);
- }
+ if (cmd == name) {
+ (void) strlcpy(buf, cmd + 2, MAXPATHLEN);
+ } else {
+ (void) strncpy(buf, name, cmd - name);
+ (void) strcpy(buf + (cmd - name), cmd + 2);
}
+ return (RES_OK);
- return (1);
-}
-
-static priv_set_t *
-get_privset(const char *s)
-{
- priv_set_t *res;
-
- if ((res = priv_str_to_set(s, ",", NULL)) == NULL) {
- (void) fprintf(stderr, "%s: bad privilege set\n", s);
- exit(EXIT_FAILURE);
- }
- return (res);
}
static void
@@ -419,171 +90,77 @@ usage(void)
exit(EXIT_FAILURE);
}
-
-/*
- * This routine exists on failure and returns NULL if no granted privileges
- * are set.
- */
-static priv_set_t *
-get_granted_privs(uid_t uid)
-{
- struct passwd *pwent;
- userattr_t *ua;
- char *profs;
- priv_set_t *res;
- char *profArray[MAXPROFS];
- int profcnt = 0;
-
- res = priv_allocset();
- if (res == NULL) {
- perror("priv_allocset");
- exit(EXIT_FAILURE);
- }
-
- priv_emptyset(res);
-
- if ((pwent = getpwuid(uid)) == NULL) {
- (void) fprintf(stderr, "%d: ", (int)uid);
- (void) fprintf(stderr, gettext("can't get passwd entry\n"));
- exit(EXIT_FAILURE);
- }
-
- ua = getusernam(pwent->pw_name);
-
- if (ua != NULL && ua->attr != NULL &&
- (profs = kva_match(ua->attr, USERATTR_PROFILES_KW)) != NULL) {
- get_profile_privs(profs, profArray, &profcnt, res);
- free_proflist(profArray, profcnt);
- }
-
- get_default_privs(pwent->pw_name, res);
-
- if (ua != NULL)
- free_userattr(ua);
-
- return (res);
-}
-
-static void
-get_default_privs(const char *user, priv_set_t *pset)
-{
- char *profs = NULL;
- char *profArray[MAXPROFS];
- int profcnt = 0;
-
- if (_get_user_defs(user, NULL, &profs) == 0) {
- /* get privileges from default profiles */
- if (profs != NULL) {
- get_profile_privs(profs, profArray, &profcnt, pset);
- free_proflist(profArray, profcnt);
- _free_user_defs(NULL, profs);
- }
- }
-}
-
-static void
-get_profile_privs(char *profiles, char **profArray, int *profcnt,
- priv_set_t *pset)
+int
+main(int argc, char **argv)
{
-
- char *prof;
- char *lasts;
- profattr_t *pa;
- char *privs;
- int i;
-
- for (prof = strtok_r(profiles, PROFLIST_SEP, &lasts);
- prof != NULL;
- prof = strtok_r(NULL, PROFLIST_SEP, &lasts))
- getproflist(prof, profArray, profcnt);
-
- /* get the privileges from list of profiles */
- for (i = 0; i < *profcnt; i++) {
-
- if ((pa = getprofnam(profArray[i])) == NULL) {
- /*
- * this should never happen.
- * unless the database has an undefined profile
- */
- continue;
+ char *cmd;
+ char *pset = NULL;
+ char pathbuf[MAXPATHLEN];
+ int c;
+ priv_set_t *wanted;
+ int oflag;
+
+ oflag = getpflags(PRIV_PFEXEC);
+ if (setpflags(PRIV_PFEXEC, 1) != 0) {
+ perror("setpflags(PRIV_PFEXEC)");
+ exit(1);
+ }
+
+ if (*argv[0] == '-')
+ cmd = argv[0] + 1;
+ else
+ cmd = argv[0];
+
+ /* Strip "pf" from argv[0], it confuses some shells. */
+ if (strncmp(cmd, "pf", 2) == 0) {
+ argv[0] += 2;
+ /* argv[0] will need to start with '-' again. */
+ if (argv[0][-2] == '-')
+ *argv[0] = '-';
+ }
+
+ /* If this fails, we just continue with plan B */
+ if (shellname(getexecname(), pathbuf) == RES_OK)
+ (void) execv(pathbuf, argv);
+
+ switch (shellname(cmd, pathbuf)) {
+ case RES_OK:
+ (void) execv(pathbuf, argv);
+ perror(pathbuf);
+ return (1);
+ case RES_PFEXEC:
+ case RES_FAILURE:
+ while ((c = getopt(argc, argv, "P:")) != EOF) {
+ switch (c) {
+ case 'P':
+ if (pset == NULL) {
+ pset = optarg;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ usage();
+ }
}
+ argc -= optind;
+ argv += optind;
+ if (argc < 1)
+ usage();
- /* get privs from this profile */
- privs = kva_match(pa->attr, PROFATTR_PRIVS_KW);
- if (privs != NULL) {
- priv_set_t *tmp = priv_str_to_set(privs, ",", NULL);
- if (tmp != NULL) {
- priv_union(tmp, pset);
- priv_freeset(tmp);
+ if (pset != NULL) {
+ wanted = priv_str_to_set(pset, ",", NULL);
+ if (setppriv(PRIV_ON, PRIV_INHERITABLE, wanted) != 0) {
+ (void) fprintf(stderr,
+ gettext("setppriv(): %s\n"),
+ strerror(errno));
+ exit(EXIT_FAILURE);
}
+ (void) setpflags(PRIV_PFEXEC, oflag);
}
- free_profattr(pa);
- }
-}
-
-/*
- * True if someone (user, group, other) can execute this file.
- */
-#define S_ISEXEC(mode) (((mode)&(S_IXUSR|S_IXGRP|S_IXOTH)) != 0)
-
-/*
- * This function can return either the first argument or dynamically
- * allocated memory. Reuse with care.
- */
-static char *
-pathsearch(char *cmd)
-{
- char *path, *dir, *result;
- char buf[MAXPATHLEN];
- struct stat stbuf;
-
- /*
- * Implement shell like PATH searching; if the pathname contains
- * one or more slashes, don't search the path, even if the '/'
- * isn't the first character. (E.g., ./command or dir/command)
- * No path equals to a search in ".", just like the shell.
- */
- if (strchr(cmd, '/') != NULL)
- return (cmd);
-
- path = getenv("PATH");
- if (path == NULL)
- return (cmd);
-
- /*
- * We need to copy $PATH because our sub processes may need it.
- */
- path = strdup(path);
- if (path == NULL) {
- perror("pfexec: strdup $PATH");
- exit(EXIT_FAILURE);
+ (void) execvp(argv[0], argv);
+ perror(argv[0]);
+ return (1);
}
-
- result = NULL;
- for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":")) {
- if (snprintf(buf, sizeof (buf), "%s/%s", dir, cmd) >=
- sizeof (buf)) {
- continue;
- }
- if (stat(buf, &stbuf) < 0)
- continue;
- /*
- * Shells typically call access() with E_OK flag
- * to determine if the effective uid can execute
- * the file. We don't know what the eventual euid
- * will be; it is determined by the exec_attr
- * attributes which depend on the full pathname of
- * the command. Therefore, we match the first regular
- * file we find that is executable by someone.
- */
- if (S_ISREG(stbuf.st_mode) && S_ISEXEC(stbuf.st_mode)) {
- result = strdup(buf);
- break;
- }
- }
- free(path);
- if (result == NULL)
- (void) fprintf(stderr, gettext("%s: Command not found\n"), cmd);
- return (result);
+ return (1);
}
diff --git a/usr/src/cmd/pfexecd/Makefile b/usr/src/cmd/pfexecd/Makefile
new file mode 100644
index 0000000000..262bef7054
--- /dev/null
+++ b/usr/src/cmd/pfexecd/Makefile
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+# Makefile for the pfexec daemon.
+#
+
+PROG= pfexecd
+MANIFEST= pfexecd.xml
+SRCS= $(PROG:%=%.c)
+lint: lint_SRCS
+
+include ../Makefile.cmd
+
+TARGET= all
+
+ROOTMANIFESTDIR= $(ROOTSVCSYSTEM)
+
+LDLIBS += -lsecdb
+
+# install macros and rule
+#
+GROUP= bin
+ROOTPROG= $(ROOTLIB)/$(PROG)
+$(ROOTPROG) := FILEMODE= 555
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all .WAIT $(ROOTPROG) $(ROOTMANIFEST) $(ROOTSVCMETHOD)
+
+clean:
+
+check: $(CHKMANIFEST)
+
+${ROOTLIB}/%: %
+ ${INS.file}
+
+lint: lint_SRCS
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/pfexecd/pfexecd.c b/usr/src/cmd/pfexecd/pfexecd.c
new file mode 100644
index 0000000000..b043c33e9c
--- /dev/null
+++ b/usr/src/cmd/pfexecd/pfexecd.c
@@ -0,0 +1,525 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ */
+
+#define _POSIX_PTHREAD_SEMANTICS 1
+
+#include <sys/param.h>
+#include <sys/klpd.h>
+#include <sys/syscall.h>
+#include <sys/systeminfo.h>
+
+#include <alloca.h>
+#include <ctype.h>
+#include <deflt.h>
+#include <door.h>
+#include <errno.h>
+#include <grp.h>
+#include <priv.h>
+#include <pwd.h>
+#include <regex.h>
+#include <secdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <auth_attr.h>
+#include <exec_attr.h>
+#include <prof_attr.h>
+#include <user_attr.h>
+
+static int doorfd = -1;
+
+static size_t repsz, setsz;
+
+static uid_t get_uid(const char *, boolean_t *, char *);
+static gid_t get_gid(const char *, boolean_t *, char *);
+static priv_set_t *get_privset(const char *, boolean_t *, char *);
+static priv_set_t *get_granted_privs(uid_t);
+
+/*
+ * Remove the isaexec path of an executable if we can't find the
+ * executable at the first attempt.
+ */
+
+static regex_t regc;
+static boolean_t cansplice = B_TRUE;
+
+static void
+init_isa_regex(void)
+{
+ char *isalist;
+ size_t isalen = 255; /* wild guess */
+ size_t len;
+ long ret;
+ char *regexpr;
+ char *p;
+
+ /*
+ * Extract the isalist(5) for userland from the kernel.
+ */
+ isalist = malloc(isalen);
+ do {
+ ret = sysinfo(SI_ISALIST, isalist, isalen);
+ if (ret == -1l) {
+ free(isalist);
+ return;
+ }
+ if (ret > isalen) {
+ isalen = ret;
+ isalist = realloc(isalist, isalen);
+ } else
+ break;
+ } while (isalist != NULL);
+
+
+ if (isalist == NULL)
+ return;
+
+ /* allocate room for the regex + (/())/[^/]*$ + needed \\. */
+#define LEFT "(/("
+#define RIGHT "))/[^/]*$"
+
+ regexpr = alloca(ret * 2 + sizeof (LEFT RIGHT));
+ (void) strcpy(regexpr, LEFT);
+ len = strlen(regexpr);
+
+ for (p = isalist; *p; p++) {
+ switch (*p) {
+ case '+':
+ case '|':
+ case '*':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ case '\\':
+ regexpr[len++] = '\\';
+ default:
+ regexpr[len++] = *p;
+ break;
+ case ' ':
+ case '\t':
+ regexpr[len++] = '|';
+ break;
+ }
+ }
+
+ free(isalist);
+ regexpr[len] = '\0';
+ (void) strcat(regexpr, RIGHT);
+
+ if (regcomp(&regc, regexpr, REG_EXTENDED) != 0)
+ return;
+
+ cansplice = B_TRUE;
+}
+
+#define NMATCH 2
+
+static boolean_t
+removeisapath(char *path)
+{
+ regmatch_t match[NMATCH];
+
+ if (!cansplice || regexec(&regc, path, NMATCH, match, 0) != 0)
+ return (B_FALSE);
+
+ /*
+ * The first match includes the whole matched expression including the
+ * end of the string. The second match includes the "/" + "isa" and
+ * that is the part we need to remove.
+ */
+
+ if (match[1].rm_so == -1)
+ return (B_FALSE);
+
+ /* match[0].rm_eo == strlen(path) */
+ (void) memmove(path + match[1].rm_so, path + match[1].rm_eo,
+ match[0].rm_eo - match[1].rm_eo + 1);
+
+ return (B_TRUE);
+}
+
+static int
+register_pfexec(int fd)
+{
+ int ret = syscall(SYS_privsys, PRIVSYS_PFEXEC_REG, fd);
+
+ return (ret);
+}
+
+/* ARGSUSED */
+static void
+unregister_pfexec(int sig)
+{
+ if (doorfd != -1)
+ (void) syscall(SYS_privsys, PRIVSYS_PFEXEC_UNREG, doorfd);
+ _exit(0);
+}
+
+static int
+alldigits(const char *s)
+{
+ int c;
+
+ if (*s == '\0')
+ return (0);
+
+ while ((c = *s++) != '\0') {
+ if (!isdigit(c)) {
+ return (0);
+ }
+ }
+
+ return (1);
+}
+
+static uid_t
+get_uid(const char *v, boolean_t *ok, char *path)
+{
+ struct passwd *pwd, pwdm;
+ char buf[1024];
+
+ if (getpwnam_r(v, &pwdm, buf, sizeof (buf), &pwd) == 0 && pwd != NULL)
+ return (pwd->pw_uid);
+
+ if (alldigits(v))
+ return (atoi(v));
+
+ *ok = B_FALSE;
+ syslog(LOG_ERR, "%s: %s: unknown username\n", path, v);
+ return ((uid_t)-1);
+}
+
+static uid_t
+get_gid(const char *v, boolean_t *ok, char *path)
+{
+ struct group *grp, grpm;
+ char buf[1024];
+
+ if (getgrnam_r(v, &grpm, buf, sizeof (buf), &grp) == 0 && grp != NULL)
+ return (grp->gr_gid);
+
+ if (alldigits(v))
+ return (atoi(v));
+
+ *ok = B_FALSE;
+ syslog(LOG_ERR, "%s: %s: unknown groupname\n", path, v);
+ return ((gid_t)-1);
+}
+
+static priv_set_t *
+get_privset(const char *s, boolean_t *ok, char *path)
+{
+ priv_set_t *res;
+
+ if ((res = priv_str_to_set(s, ",", NULL)) == NULL) {
+ syslog(LOG_ERR, "%s: %s: bad privilege set\n", path, s);
+ if (ok != NULL)
+ *ok = B_FALSE;
+ }
+ return (res);
+}
+
+/*ARGSUSED*/
+static int
+ggp_callback(const char *prof, kva_t *attr, void *ctxt, void *vres)
+{
+ priv_set_t *res = vres;
+ char *privs;
+
+ if (attr == NULL)
+ return (0);
+
+ /* get privs from this profile */
+ privs = kva_match(attr, PROFATTR_PRIVS_KW);
+ if (privs != NULL) {
+ priv_set_t *tmp = priv_str_to_set(privs, ",", NULL);
+ if (tmp != NULL) {
+ priv_union(tmp, res);
+ priv_freeset(tmp);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * This routine exists on failure and returns NULL if no granted privileges
+ * are set.
+ */
+static priv_set_t *
+get_granted_privs(uid_t uid)
+{
+ priv_set_t *res;
+ struct passwd *pwd, pwdm;
+ char buf[1024];
+
+ if (getpwuid_r(uid, &pwdm, buf, sizeof (buf), &pwd) != 0 || pwd == NULL)
+ return (NULL);
+
+ res = priv_allocset();
+ if (res == NULL)
+ return (NULL);
+
+ priv_emptyset(res);
+
+ (void) _enum_profs(pwd->pw_name, ggp_callback, NULL, res);
+
+ return (res);
+}
+
+static void
+callback_forced_privs(pfexec_arg_t *pap)
+{
+ execattr_t *exec;
+ char *value;
+ priv_set_t *fset;
+ void *res = alloca(setsz);
+
+ /* Empty set signifies no forced privileges. */
+ priv_emptyset(res);
+
+ exec = getexecprof("Forced Privilege", KV_COMMAND, pap->pfa_path,
+ GET_ONE);
+
+ if (exec == NULL && removeisapath(pap->pfa_path)) {
+ exec = getexecprof("Forced Privilege", KV_COMMAND,
+ pap->pfa_path, GET_ONE);
+ }
+
+ if (exec == NULL) {
+ (void) door_return(res, setsz, NULL, 0);
+ return;
+ }
+
+ if ((value = kva_match(exec->attr, EXECATTR_IPRIV_KW)) == NULL ||
+ (fset = get_privset(value, NULL, pap->pfa_path)) == NULL) {
+ free_execattr(exec);
+ (void) door_return(res, setsz, NULL, 0);
+ return;
+ }
+
+ priv_copyset(fset, res);
+ priv_freeset(fset);
+
+ free_execattr(exec);
+ (void) door_return(res, setsz, NULL, 0);
+}
+
+static void
+callback_user_privs(pfexec_arg_t *pap)
+{
+ priv_set_t *gset, *wset;
+ uint32_t res;
+
+ wset = (priv_set_t *)&pap->pfa_buf;
+ gset = get_granted_privs(pap->pfa_uid);
+
+ res = priv_issubset(wset, gset);
+ priv_freeset(gset);
+
+ (void) door_return((char *)&res, sizeof (res), NULL, 0);
+}
+
+static void
+callback_pfexec(pfexec_arg_t *pap)
+{
+ pfexec_reply_t *res = alloca(repsz);
+ uid_t uid, euid, uuid;
+ gid_t gid, egid;
+ struct passwd pw, *pwd;
+ char buf[1024];
+ execattr_t *exec;
+ char *value;
+ priv_set_t *lset, *iset;
+ size_t mysz = repsz - 2 * setsz;
+ char *path = pap->pfa_path;
+
+ uuid = pap->pfa_uid;
+
+ if (getpwuid_r(uuid, &pw, buf, sizeof (buf), &pwd) != 0 || pwd == NULL)
+ goto stdexec;
+
+ exec = getexecuser(pwd->pw_name, KV_COMMAND, path, GET_ONE);
+
+ if (exec == NULL && removeisapath(path))
+ exec = getexecuser(pwd->pw_name, KV_COMMAND, path, GET_ONE);
+
+ if (exec == NULL) {
+ res->pfr_allowed = B_FALSE;
+ goto ret;
+ }
+
+ if (exec->attr == NULL)
+ goto stdexec;
+
+ /* Found in execattr, so clearly we can use it */
+ res->pfr_allowed = B_TRUE;
+
+ uid = euid = (uid_t)-1;
+ gid = egid = (gid_t)-1;
+ lset = iset = NULL;
+
+ /*
+ * If there's an error in parsing uid, gid, privs, then return
+ * failure.
+ */
+ if ((value = kva_match(exec->attr, EXECATTR_UID_KW)) != NULL)
+ euid = uid = get_uid(value, &res->pfr_allowed, path);
+
+ if ((value = kva_match(exec->attr, EXECATTR_GID_KW)) != NULL)
+ egid = gid = get_gid(value, &res->pfr_allowed, path);
+
+ if ((value = kva_match(exec->attr, EXECATTR_EUID_KW)) != NULL)
+ euid = get_uid(value, &res->pfr_allowed, path);
+
+ if ((value = kva_match(exec->attr, EXECATTR_EGID_KW)) != NULL)
+ egid = get_gid(value, &res->pfr_allowed, path);
+
+ if ((value = kva_match(exec->attr, EXECATTR_LPRIV_KW)) != NULL)
+ lset = get_privset(value, &res->pfr_allowed, path);
+
+ if ((value = kva_match(exec->attr, EXECATTR_IPRIV_KW)) != NULL)
+ iset = get_privset(value, &res->pfr_allowed, path);
+
+ /*
+ * Remove LD_* variables in the kernel when the runtime linker might
+ * use them later on because the uids are equal.
+ */
+ res->pfr_scrubenv = (uid != (uid_t)-1 && euid == uid) ||
+ (gid != (gid_t)-1 && egid == gid) || iset != NULL;
+
+ res->pfr_euid = euid;
+ res->pfr_ruid = uid;
+ res->pfr_egid = egid;
+ res->pfr_rgid = gid;
+
+ /* Now add the privilege sets */
+ res->pfr_ioff = res->pfr_loff = 0;
+ if (iset != NULL) {
+ res->pfr_ioff = mysz;
+ priv_copyset(iset, PFEXEC_REPLY_IPRIV(res));
+ mysz += setsz;
+ priv_freeset(iset);
+ }
+ if (lset != NULL) {
+ res->pfr_loff = mysz;
+ priv_copyset(lset, PFEXEC_REPLY_LPRIV(res));
+ mysz += setsz;
+ priv_freeset(lset);
+ }
+
+ res->pfr_setcred = uid != (uid_t)-1 || euid != (uid_t)-1 ||
+ egid != (gid_t)-1 || gid != (gid_t)-1 || iset != NULL ||
+ lset != NULL;
+
+ /* If the real uid changes, we stop running under a profile shell */
+ res->pfr_clearflag = uid != (uid_t)-1 && uid != uuid;
+ free_execattr(exec);
+ret:
+ (void) door_return((char *)res, mysz, NULL, 0);
+ return;
+
+stdexec:
+ res->pfr_scrubenv = B_FALSE;
+ res->pfr_setcred = B_FALSE;
+ res->pfr_allowed = B_TRUE;
+
+ (void) door_return((char *)res, mysz, NULL, 0);
+}
+
+/* ARGSUSED */
+static void
+callback(void *cookie, char *argp, size_t asz, door_desc_t *dp, uint_t ndesc)
+{
+ /* LINTED ALIGNMENT */
+ pfexec_arg_t *pap = (pfexec_arg_t *)argp;
+
+ if (asz < sizeof (pfexec_arg_t) || pap->pfa_vers != PFEXEC_ARG_VERS) {
+ (void) door_return(NULL, 0, NULL, 0);
+ return;
+ }
+
+ switch (pap->pfa_call) {
+ case PFEXEC_EXEC_ATTRS:
+ callback_pfexec(pap);
+ break;
+ case PFEXEC_FORCED_PRIVS:
+ callback_forced_privs(pap);
+ break;
+ case PFEXEC_USER_PRIVS:
+ callback_user_privs(pap);
+ break;
+ default:
+ syslog(LOG_ERR, "Bad Call: %d\n", pap->pfa_call);
+ break;
+ }
+
+ /*
+ * If the door_return(ptr, size, NULL, 0) fails, make sure we
+ * don't lose server threads.
+ */
+ (void) door_return(NULL, 0, NULL, 0);
+}
+
+int
+main(void)
+{
+ const priv_impl_info_t *info;
+
+ (void) signal(SIGINT, unregister_pfexec);
+ (void) signal(SIGQUIT, unregister_pfexec);
+ (void) signal(SIGTERM, unregister_pfexec);
+ (void) signal(SIGHUP, unregister_pfexec);
+
+ info = getprivimplinfo();
+ if (info == NULL)
+ exit(1);
+
+ if (fork() > 0)
+ _exit(0);
+
+ openlog("pfexecd", LOG_PID, LOG_DAEMON);
+ setsz = info->priv_setsize * sizeof (priv_chunk_t);
+ repsz = 2 * setsz + sizeof (pfexec_reply_t);
+
+ init_isa_regex();
+
+ doorfd = door_create(callback, NULL, DOOR_REFUSE_DESC);
+
+ if (doorfd == -1 || register_pfexec(doorfd) != 0) {
+ perror("doorfd");
+ exit(1);
+ }
+
+ /* LINTED CONSTCOND */
+ while (1)
+ (void) sigpause(SIGINT);
+
+ return (0);
+}
diff --git a/usr/src/cmd/pfexecd/pfexecd.xml b/usr/src/cmd/pfexecd/pfexecd.xml
new file mode 100644
index 0000000000..c13249e4b6
--- /dev/null
+++ b/usr/src/cmd/pfexecd/pfexecd.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+ NOTE: This service manifest is not editable; its contents will
+ be overwritten by package or patch operations, including
+ operating system upgrade. Make customizations in a different
+ file.
+-->
+
+<service_bundle type='manifest' name='SUNWcs:pfexec'>
+
+<service
+ name='system/pfexec'
+ type='service'
+ version='1'>
+
+ <create_default_instance enabled='true' />
+
+ <single_instance />
+
+ <dependency
+ name='usr'
+ type='service'
+ grouping='require_all'
+ restart_on='none'>
+ <service_fmri value='svc:/system/filesystem/usr' />
+ </dependency>
+
+ <exec_method
+ type='method'
+ name='start'
+ exec='/usr/lib/pfexecd'
+ timeout_seconds='60'>
+ </exec_method>
+
+ <exec_method
+ type='method'
+ name='stop'
+ exec=':kill'
+ timeout_seconds='60'>
+ </exec_method>
+
+ <exec_method
+ type='method'
+ name='refresh'
+ exec=':kill'
+ timeout_seconds='60'>
+ </exec_method>
+
+ <property_group name='options' type='application'>
+ </property_group>
+
+ <stability value='Unstable' />
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>
+ Supports in-kernel pfexec and forced privileges.
+ </loctext>
+ </common_name>
+ </template>
+</service>
+
+</service_bundle>
diff --git a/usr/src/cmd/profiles/profiles.c b/usr/src/cmd/profiles/profiles.c
index 8ac26920a4..265fd0c22e 100644
--- a/usr/src/cmd/profiles/profiles.c
+++ b/usr/src/cmd/profiles/profiles.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <stdio.h>
@@ -51,17 +50,10 @@
#define TEXT_DOMAIN "SYS_TEST"
#endif
-#define PROFLIST_SEP ","
-
-
static void usage();
static int show_profs(char *, int);
-static int list_profs(userattr_t *, int);
static void print_profs_long(execattr_t *);
-static void print_profs(char **, int, int);
-static void getProfiles(char *, char **, int *);
-static void getDefaultProfiles(char *, char **, int *);
-static void print_profile_privs(const char *);
+static void print_profile_privs(kva_t *);
static char *progname = "profiles";
@@ -110,15 +102,31 @@ main(int argc, char *argv[])
return (status);
}
+static int
+show_profs_callback(const char *prof, kva_t *pa, void *pflag, void *vcnt)
+{
+ char *indent = "";
+ const int *print_flag = pflag;
+ int *pcnt = vcnt;
+
+ (*pcnt)++;
+
+ if ((*print_flag) & PRINT_NAME) {
+ indent = " ";
+ }
+
+ (void) printf("%s%s", indent, prof);
+ print_profile_privs(pa);
+ (void) printf("\n");
+
+ return (0);
+}
static int
show_profs(char *username, int print_flag)
{
int status = EXIT_OK;
struct passwd *pw;
- userattr_t *user;
- char *profArray[MAXPROFS];
- int profcnt = 0;
execattr_t *exec;
if (username == NULL) {
@@ -135,76 +143,33 @@ show_profs(char *username, int print_flag)
(void) fprintf(stderr, gettext("No such user\n"));
return (status);
}
- if (username != NULL) {
- if ((user = getusernam(username)) != NULL) {
- status = list_profs(user, print_flag);
- } else {
- getDefaultProfiles(username, profArray, &profcnt);
- if (profcnt == 0) {
- status = EXIT_NON_FATAL;
- } else {
- if (print_flag & PRINT_LONG) {
- exec = getexecuser(username, KV_COMMAND,
- NULL, GET_ALL|__SEARCH_ALL_POLS);
- print_profs_long(exec);
- free_execattr(exec);
- } else {
- print_profs(profArray, print_flag,
- profcnt);
- }
- }
- }
- }
-
- if (status == EXIT_NON_FATAL) {
- (void) fprintf(stderr, "%s: %s: ", progname, username);
- (void) fprintf(stderr, gettext("No profiles\n"));
- }
-
- return (status);
-}
-
-
-static int
-list_profs(userattr_t *user, int print_flag)
-{
- int status = EXIT_OK;
- char *proflist = (char *)NULL;
- execattr_t *exec = (execattr_t *)NULL;
- char *profArray[MAXPROFS];
- int profcnt = 0;
if (print_flag & PRINT_LONG) {
- exec = getexecuser(user->name, KV_COMMAND, NULL,
+ exec = getexecuser(username, KV_COMMAND, NULL,
GET_ALL|__SEARCH_ALL_POLS);
- if (exec == NULL) {
+ if (exec != NULL) {
+ print_profs_long(exec);
+ free_execattr(exec);
+ } else {
status = EXIT_NON_FATAL;
}
} else {
- proflist = kva_match(user->attr, USERATTR_PROFILES_KW);
- if (proflist != NULL) {
- getProfiles(proflist, profArray, &profcnt);
- }
- /* Also get any default profiles */
- getDefaultProfiles(user->name, profArray, &profcnt);
- if (profcnt == 0) {
+ int cnt = 0;
+ (void) _enum_profs(username, show_profs_callback, &print_flag,
+ &cnt);
+
+ if (cnt == 0)
status = EXIT_NON_FATAL;
- }
}
- if (status == EXIT_OK) {
- if (print_flag & PRINT_LONG) {
- print_profs_long(exec);
- free_execattr(exec);
- } else {
- print_profs(profArray, print_flag, profcnt);
- }
+
+ if (status == EXIT_NON_FATAL) {
+ (void) fprintf(stderr, "%s: %s: ", progname, username);
+ (void) fprintf(stderr, gettext("No profiles\n"));
}
- free_userattr(user);
return (status);
}
-
/*
* print extended profile information.
*
@@ -242,9 +207,16 @@ print_profs_long(execattr_t *exec)
for (curprofile = ""; exec != NULL; exec = exec->next) {
/* print profile name if it is a new one */
if (strcmp(curprofile, exec->name) != 0) {
+ profattr_t *pa;
curprofile = exec->name;
+
(void) printf(" %s", curprofile);
- print_profile_privs(curprofile);
+
+ pa = getprofnam(curprofile);
+ if (pa != NULL) {
+ print_profile_privs(pa->attr);
+ free_profattr(pa);
+ }
(void) printf("\n");
}
len = printf(" %s ", exec->id);
@@ -289,66 +261,13 @@ usage()
}
static void
-getProfiles(char *profiles, char **profArray, int *profcnt) {
-
- char *prof;
- char *lasts;
-
- for (prof = (char *)strtok_r(profiles, PROFLIST_SEP, &lasts);
- prof != NULL;
- prof = (char *)strtok_r(NULL, PROFLIST_SEP, &lasts)) {
-
- getproflist(prof, profArray, profcnt);
-
- }
-}
-
-static void
-print_profile_privs(const char *profile)
+print_profile_privs(kva_t *attr)
{
- profattr_t *prof_entry = getprofnam(profile);
char *privs;
- if (prof_entry) {
- privs = kva_match(prof_entry->attr, PROFATTR_PRIVS_KW);
+ if (attr) {
+ privs = kva_match(attr, PROFATTR_PRIVS_KW);
if (privs)
(void) printf(" privs=%s", privs);
- free_profattr(prof_entry);
- }
-}
-
-static void
-print_profs(char **profnames, int print_flag, int profcnt)
-{
-
- int i;
- char *indent = "";
-
- if (print_flag & PRINT_NAME) {
- indent = " ";
- }
-
- for (i = 0; i < profcnt; i++) {
- (void) printf("%s%s", indent, profnames[i]);
- print_profile_privs(profnames[i]);
- (void) printf("\n");
- }
-
- free_proflist(profnames, profcnt);
-}
-
-/*
- * Get the list of default profiles from /etc/security/policy.conf
- */
-static void
-getDefaultProfiles(char *user, char **profArray, int *profcnt)
-{
- char *profs = NULL;
-
- if (_get_user_defs(user, NULL, &profs) == 0) {
- if (profs != NULL) {
- getProfiles(profs, profArray, profcnt);
- _free_user_defs(NULL, profs);
- }
}
}
diff --git a/usr/src/cmd/ptools/ppriv/ppriv.c b/usr/src/cmd/ptools/ppriv/ppriv.c
index d9a155a959..a695c1a09b 100644
--- a/usr/src/cmd/ptools/ppriv/ppriv.c
+++ b/usr/src/cmd/ptools/ppriv/ppriv.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Program to examine or set process privileges.
*/
@@ -60,6 +59,7 @@ static boolean_t Don = B_FALSE;
static boolean_t Doff = B_FALSE;
static boolean_t list = B_FALSE;
static boolean_t mac_aware = B_FALSE;
+static boolean_t pfexec = B_FALSE;
static boolean_t xpol = B_FALSE;
static int mode = PRIV_STR_PORT;
@@ -78,7 +78,7 @@ main(int argc, char **argv)
else
command = argv[0];
- while ((opt = getopt(argc, argv, "lDMNevs:xS")) != EOF) {
+ while ((opt = getopt(argc, argv, "lDMNPevs:xS")) != EOF) {
switch (opt) {
case 'l':
list = B_TRUE;
@@ -94,6 +94,10 @@ main(int argc, char **argv)
set = B_TRUE;
Doff = B_TRUE;
break;
+ case 'P':
+ set = B_TRUE;
+ pfexec = B_TRUE;
+ break;
case 'e':
exec = B_TRUE;
break;
@@ -493,7 +497,7 @@ privupdate(prpriv_t *pr, const char *arg)
}
}
- if (Doff || Don || xpol) {
+ if (Doff || Don || pfexec || xpol) {
priv_info_uint_t *pii;
int sz = PRIV_PRPRIV_SIZE(pr);
char *x = (char *)pr + PRIV_PRPRIV_INFO_OFFSET(pr);
@@ -530,6 +534,8 @@ done:
fl |= PRIV_DEBUG;
if (Doff)
fl &= ~PRIV_DEBUG;
+ if (pfexec)
+ fl |= PRIV_PFEXEC;
if (xpol)
fl |= PRIV_XPOLICY;
@@ -552,6 +558,10 @@ privupdate_self(void)
if (setpflags(NET_MAC_AWARE_INHERIT, 1) != 0)
fatal("setpflags(NET_MAC_AWARE_INHERIT)");
}
+ if (pfexec) {
+ if (setpflags(PRIV_PFEXEC, 1) != 0)
+ fatal("setpflags(PRIV_PFEXEC)");
+ }
if (sets != NULL) {
priv_set_t *target = priv_allocset();
@@ -592,6 +602,8 @@ privupdate_self(void)
(void) setpflags(PRIV_DEBUG, Don ? 1 : 0);
if (xpol)
(void) setpflags(PRIV_XPOLICY, 1);
+ if (pfexec)
+ (void) setpflags(PRIV_PFEXEC, 1);
}
static int
@@ -649,6 +661,7 @@ static struct {
{ PRIV_AWARE_INHERIT, "PRIV_AWARE_INHERIT" },
{ PRIV_AWARE_RESET, "PRIV_AWARE_RESET" },
{ PRIV_XPOLICY, "PRIV_XPOLICY" },
+ { PRIV_PFEXEC, "PRIV_PFEXEC" },
{ NET_MAC_AWARE, "NET_MAC_AWARE" },
{ NET_MAC_AWARE_INHERIT, "NET_MAC_AWARE_INHERIT" },
};
diff --git a/usr/src/cmd/sh/Makefile b/usr/src/cmd/sh/Makefile
index a2660213d0..78db168423 100644
--- a/usr/src/cmd/sh/Makefile
+++ b/usr/src/cmd/sh/Makefile
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
#
PROG = sh
@@ -29,7 +28,7 @@ USR_PROG = $(PROG)
OBJS= args.o blok.o cmd.o defs.o error.o fault.o hash.o hashserv.o \
io.o msg.o print.o stak.o string.o word.o xec.o \
ctype.o echo.o expand.o func.o macro.o pwd.o setbrk.o test.o \
- bltin.o jobs.o ulimit.o sh_policy.o main.o name.o service.o
+ bltin.o jobs.o ulimit.o main.o name.o service.o
SRCS= $(OBJS:%.o=%.c)
include ../Makefile.cmd
@@ -47,7 +46,7 @@ XGETFLAGS += -a -x sh.xcl
CPPFLAGS += -D_FILE_OFFSET_BITS=64 -DACCT
MAPFILES = $(MAPFILE.INT) $(MAPFILE.NGB)
LDFLAGS += $(MAPFILES:%=-M%)
-LDLIBS += -lgen -lsecdb
+LDLIBS += -lgen
.KEEP_STATE:
@@ -66,8 +65,6 @@ $(POFILE): $(POFILES)
install: all $(ROOTHASBINPROG)
$(RM) $(ROOTHASBIN)/jsh
$(SYMLINK) sh $(ROOTHASBIN)/jsh
- $(RM) $(ROOTHASBIN)/pfsh
- $(SYMLINK) sh $(ROOTHASBIN)/pfsh
$(RM) $(ROOTHASLIB)/rsh
$(SYMLINK) ../bin/sh $(ROOTHASLIB)/rsh
diff --git a/usr/src/cmd/sh/main.c b/usr/src/cmd/sh/main.c
index 9533e793cc..df42009b5b 100644
--- a/usr/src/cmd/sh/main.c
+++ b/usr/src/cmd/sh/main.c
@@ -20,14 +20,12 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* UNIX shell
*/
@@ -40,7 +38,6 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include "dup.h"
-#include "sh_policy.h"
#ifdef RES
#include <sgtty.h>
@@ -141,15 +138,6 @@ main(int c, char *v[], char *e[])
(void) textdomain(TEXT_DOMAIN);
/*
- * This is a profile shell if the simple name of argv[0] is
- * pfsh or -pfsh
- */
- if (c > 0 && (eq("pfsh", simple(*v)) || eq("-pfsh", simple(*v)))) {
- flags |= pfshflg;
- secpolicy_init();
- }
-
- /*
* 'rsflag' is zero if SHELL variable is
* set in environment and
* the simple file part of the value.
@@ -600,23 +588,3 @@ setmode(int prof)
flags &= ~prompt;
}
}
-
-/*
- * A generic call back routine to output error messages from the
- * policy backing functions called by pfsh.
- *
- * msg must contain '\n' if a new line is to be printed.
- */
-void
-secpolicy_print(int level, const char *msg)
-{
- switch (level) {
- case SECPOLICY_WARN:
- default:
- prs(_gettext(msg));
- return;
- case SECPOLICY_ERROR:
- error(msg);
- break;
- }
-}
diff --git a/usr/src/cmd/sh/service.c b/usr/src/cmd/sh/service.c
index e666aafc65..e74a35b471 100644
--- a/usr/src/cmd/sh/service.c
+++ b/usr/src/cmd/sh/service.c
@@ -20,15 +20,12 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* UNIX shell
*/
@@ -36,7 +33,6 @@
#include "defs.h"
#include <errno.h>
#include <fcntl.h>
-#include "sh_policy.h"
#define ARGMK 01
@@ -202,7 +198,8 @@ catpath(unsigned char *path, unsigned char *name)
if (argp >= brkend)
growstak(argp);
}
- while (*argp++ = *scanp++);
+ while (*argp++ = *scanp++)
+ ;
return (path);
}
@@ -253,7 +250,6 @@ execa(unsigned char *at[], short pos)
static unsigned char *
execs(unsigned char *ap, unsigned char *t[])
{
- int pfstatus = NOATTRS;
unsigned char *p, *prefix;
unsigned char *savptr;
@@ -261,28 +257,8 @@ execs(unsigned char *ap, unsigned char *t[])
trim(p = curstak());
sigchk();
- if (flags & pfshflg) {
- /*
- * Need to save the stack information, or the
- * first memory allocation in secpolicy_profile_lookup()
- * will clobber it.
- */
- savptr = endstak(p + strlen((const char *)p) + 1);
-
- pfstatus = secpolicy_pfexec((const char *)p,
- (char **)t, (const char **)xecenv);
-
- if (pfstatus != NOATTRS) {
- errno = pfstatus;
- }
-
- tdystak(savptr);
- }
-
- if (pfstatus == NOATTRS) {
- execve((const char *)p, (char *const *)&t[0],
- (char *const *)xecenv);
- }
+ execve((const char *)p, (char *const *)&t[0],
+ (char *const *)xecenv);
switch (errno) {
case ENOEXEC: /* could be a shell script */
@@ -351,7 +327,7 @@ trim(unsigned char *at)
last = at;
while (c = *current) {
if ((len = mbtowc(&wc, (char *)current,
- MB_LEN_MAX)) <= 0) {
+ MB_LEN_MAX)) <= 0) {
*last++ = c;
current++;
continue;
@@ -369,7 +345,7 @@ trim(unsigned char *at)
current++;
if (c = *current) {
if ((len = mbtowc(&wc, (char *)current,
- MB_LEN_MAX)) <= 0) {
+ MB_LEN_MAX)) <= 0) {
*last++ = c;
current++;
continue;
@@ -676,7 +652,7 @@ doacct(void)
sabuf.ac_etime = compress(after - before);
if ((fd = open((char *)acctnod.namval,
- O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) {
+ O_WRONLY | O_APPEND | O_CREAT, 0666)) != -1) {
write(fd, &sabuf, sizeof (sabuf));
close(fd);
}
diff --git a/usr/src/cmd/sh/sh_policy.c b/usr/src/cmd/sh/sh_policy.c
deleted file mode 100644
index d9102e3381..0000000000
--- a/usr/src/cmd/sh/sh_policy.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- *
- * Policy backing functions for kpolicy=suser,profiles=yes
- *
- */
-
-#include <sys/param.h>
-#include <grp.h>
-#include <pwd.h>
-#include <strings.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include "sh_policy.h"
-
-
-static char *username;
-
-/*
- * get the ruid and passwd name
- */
-void
-secpolicy_init(void)
-{
- uid_t ruid;
- struct passwd *passwd_ent;
-
- if (username != NULL) {
- free(username);
- username = NULL;
- }
-
- ruid = getuid();
-
- if ((passwd_ent = getpwuid(ruid)) == NULL) {
- secpolicy_print(SECPOLICY_ERROR, ERR_PASSWD);
- } else if ((username = strdup(passwd_ent->pw_name)) == NULL) {
- secpolicy_print(SECPOLICY_ERROR, ERR_MEM);
- }
-}
-
-
-/*
- * stuff pfexec full path at the begining of the argument vector
- * for the command to be pfexec'd
- *
- * return newly allocated argv on success, else return NULL.
- */
-static char **
-secpolicy_set_argv(char **arg_v)
-{
- int i;
- int arg_c = 0;
- char **pfarg_v = NULL;
-
- if (*arg_v == NULL) {
- return (pfarg_v);
- }
- for (i = 0; arg_v[i] != NULL; i++) {
- arg_c++;
- }
- /* +2 for PFEXEC and null termination */
- if ((pfarg_v = calloc(arg_c + 2, sizeof (char *))) == NULL) {
- return (pfarg_v);
- }
- pfarg_v[0] = PFEXEC;
- for (i = 0; i < arg_c; i++) {
- pfarg_v[i + 1] = arg_v[i];
- }
-
- return (pfarg_v);
-}
-
-
-/*
- * gets realpath for cmd.
- * return 0 on success, else return ENOENT.
- */
-static int
-secpolicy_getrealpath(const char *cmd, char *cmd_realpath)
-{
- register char *mover;
- char cwd[MAXPATHLEN];
-
- /*
- * What about relative paths? Were we passed one?
- */
- mover = (char *)cmd;
- if (*mover != '/') {
- /*
- * Everything in here will be considered a relative
- * path, and therefore we need to prepend cwd to it.
- */
- if (getcwd(cwd, MAXPATHLEN) == NULL) {
- secpolicy_print(SECPOLICY_ERROR, ERR_CWD);
- }
- strcat(cwd, "/");
- if (strlcat(cwd, cmd, MAXPATHLEN) >= MAXPATHLEN) {
- return (ENOENT);
- }
- mover = cwd;
- }
- /*
- * Resolve ".." and other such nonsense.
- * Now, is there *REALLY* a file there?
- */
- if (realpath(mover, cmd_realpath) == NULL) {
- return (ENOENT);
- }
-
- return (0);
-}
-
-
-/*
- * check if the command has execution attributes
- * return -
- * - NOATTRS : command in profile but has no execution attributes
- * - ENOMEM : memory allocation errors
- * - ENOENT : command not in profile
- */
-
-int
-secpolicy_pfexec(const char *command, char **arg_v, const char **xecenv)
-{
- register int status = NOATTRS;
- char **pfarg_v = (char **)NULL;
- char cmd_realpath[MAXPATHLEN + 1];
- execattr_t *exec;
-
- if ((status = secpolicy_getrealpath(command, cmd_realpath)) != 0) {
- return (status);
- }
- if ((exec = getexecuser(username, KV_COMMAND,
- (const char *)cmd_realpath, GET_ONE)) == NULL) {
- /*
- * command not in profile
- */
- return (ENOENT);
- }
- /*
- * In case of "All" profile, we'd go through pfexec
- * if it had any attributes.
- */
- if ((exec->attr != NULL) && (exec->attr->length != 0)) {
- /*
- * command in profile and has attributes
- */
- free_execattr(exec);
- arg_v[0] = (char *)command;
- pfarg_v = secpolicy_set_argv(arg_v);
- if (pfarg_v != NULL) {
- errno = 0;
- if (xecenv == NULL) {
- execv(PFEXEC, (char *const *)pfarg_v);
- } else {
- execve(PFEXEC, (char *const *)pfarg_v,
- (char *const *)xecenv);
- }
- free(pfarg_v);
- status = errno;
- } else {
- status = ENOMEM;
- }
- } else {
- /*
- * command in profile, but has no attributes
- */
- free_execattr(exec);
- status = NOATTRS;
- }
-
-
- return (status);
-}
diff --git a/usr/src/cmd/sh/sh_policy.h b/usr/src/cmd/sh/sh_policy.h
deleted file mode 100644
index 6efd47ca52..0000000000
--- a/usr/src/cmd/sh/sh_policy.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 1999 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#ifndef _SH_POLICY_H
-#define _SH_POLICY_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <exec_attr.h>
-
-#define PFEXEC "/usr/bin/pfexec"
-#define ALL_PROFILE "All"
-
-#define ERR_PASSWD "can't get passwd entry"
-#define ERR_MEM "can't allocate memory"
-#define ERR_CWD "can't get current working directory"
-#define ERR_PATH "resolved pathname too large"
-#define ERR_PROFILE "not in profile"
-#define ERR_REALPATH "can't get real path"
-
-#define NOATTRS 0 /* command in profile but w'out attributes */
-
-#define SECPOLICY_WARN 1
-#define SECPOLICY_ERROR 2
-
-/*
- * Shell Policy Interface Functions
- */
-extern void secpolicy_init(void);
-extern int secpolicy_pfexec(const char *, char **, const char **);
-extern void secpolicy_print(int, const char *);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SH_POLICY_H */
diff --git a/usr/src/cmd/svc/configd/rc_node.c b/usr/src/cmd/svc/configd/rc_node.c
index 5dbbce2091..a8aa4c32a7 100644
--- a/usr/src/cmd/svc/configd/rc_node.c
+++ b/usr/src/cmd/svc/configd/rc_node.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -114,9 +113,7 @@
* proceed if the user has been assigned at least one of a set of
* authorization strings. The set of enabling authorizations depends on the
* operation and the target object. The set of authorizations assigned to
- * a user is determined by reading /etc/security/policy.conf, querying the
- * user_attr database, and possibly querying the prof_attr database, as per
- * chkauthattr() in libsecdb.
+ * a user is determined by an algorithm defined in libsecdb.
*
* The fastest way to decide whether the two sets intersect is by entering the
* strings into a hash table and detecting collisions, which takes linear time
@@ -360,7 +357,6 @@
#include <libuutil.h>
#include <libscf.h>
#include <libscf_priv.h>
-#include <prof_attr.h>
#include <pthread.h>
#include <pwd.h>
#include <stdio.h>
@@ -369,7 +365,7 @@
#include <sys/types.h>
#include <syslog.h>
#include <unistd.h>
-#include <user_attr.h>
+#include <secdb.h>
#include "configd.h"
@@ -388,8 +384,6 @@
#define AUTH_PROP_MODIFY "modify_authorization"
#define AUTH_PROP_VALUE "value_authorization"
#define AUTH_PROP_READ "read_authorization"
-/* libsecdb should take care of this. */
-#define RBAC_AUTH_SEP ","
#define MAX_VALID_CHILDREN 3
@@ -1498,29 +1492,24 @@ perm_add_enabling(permcheck_t *pcp, const char *auth)
* perm_granted() returns PERM_GRANTED if the current door caller has one of
* the enabling authorizations in pcp, PERM_DENIED if it doesn't, PERM_GONE if
* the door client went away and PERM_FAIL if an error (usually lack of
- * memory) occurs. check_auth_list() checks an RBAC_AUTH_SEP-separated
- * list of authorizations for existence in pcp, and check_prof_list()
- * checks the authorizations granted to an RBAC_AUTH_SEP-separated list of
- * profiles.
+ * memory) occurs. auth_cb() checks each and every authorizations as
+ * enumerated by _enum_auths. When we find a result other than PERM_DENIED,
+ * we short-cut the enumeration and return non-zero.
*/
-static perm_status_t
-check_auth_list(permcheck_t *pcp, char *authlist)
-{
- char *auth, *lasts;
- perm_status_t ret;
- for (auth = (char *)strtok_r(authlist, RBAC_AUTH_SEP, &lasts);
- auth != NULL;
- auth = (char *)strtok_r(NULL, RBAC_AUTH_SEP, &lasts)) {
- if (strchr(auth, KV_WILDCHAR) == NULL)
- ret = pc_exists(pcp, auth);
- else
- ret = pc_match(pcp, auth);
+static int
+auth_cb(const char *auth, void *ctxt, void *vres)
+{
+ permcheck_t *pcp = ctxt;
+ int *pret = vres;
- if (ret != PERM_DENIED)
- return (ret);
- }
+ if (strchr(auth, KV_WILDCHAR) == NULL)
+ *pret = pc_exists(pcp, auth);
+ else
+ *pret = pc_match(pcp, auth);
+ if (*pret != PERM_DENIED)
+ return (1);
/*
* If we failed, choose the most specific auth string for use in
* the audit event.
@@ -1528,40 +1517,7 @@ check_auth_list(permcheck_t *pcp, char *authlist)
assert(pcp->pc_specific != NULL);
pcp->pc_auth_string = pcp->pc_specific->pce_auth;
- return (PERM_DENIED);
-}
-
-static perm_status_t
-check_prof_list(permcheck_t *pcp, char *proflist)
-{
- char *prof, *lasts, *authlist, *subproflist;
- profattr_t *pap;
- perm_status_t ret = PERM_DENIED;
-
- for (prof = strtok_r(proflist, RBAC_AUTH_SEP, &lasts);
- prof != NULL;
- prof = strtok_r(NULL, RBAC_AUTH_SEP, &lasts)) {
- pap = getprofnam(prof);
- if (pap == NULL)
- continue;
-
- authlist = kva_match(pap->attr, PROFATTR_AUTHS_KW);
- if (authlist != NULL)
- ret = check_auth_list(pcp, authlist);
-
- if (ret == PERM_DENIED) {
- subproflist = kva_match(pap->attr, PROFATTR_PROFS_KW);
- if (subproflist != NULL)
- /* depth check to avoid infinite recursion? */
- ret = check_prof_list(pcp, subproflist);
- }
-
- free_profattr(pap);
- if (ret != PERM_DENIED)
- return (ret);
- }
-
- return (ret);
+ return (0); /* Tells that we need to continue */
}
static perm_status_t
@@ -1570,10 +1526,7 @@ perm_granted(permcheck_t *pcp)
ucred_t *uc;
perm_status_t ret = PERM_DENIED;
- int rv;
uid_t uid;
- userattr_t *uap;
- char *authlist, *userattr_authlist, *proflist, *def_prof = NULL;
struct passwd pw;
char pwbuf[1024]; /* XXX should be NSS_BUFLEN_PASSWD */
@@ -1606,51 +1559,12 @@ perm_granted(permcheck_t *pcp)
}
/*
- * Get user's default authorizations from policy.conf
+ * Enumerate all the auths defined for the user and return the
+ * result in ret.
*/
- rv = _get_user_defs(pw.pw_name, &authlist, &def_prof);
-
- if (rv != 0)
+ if (_enum_auths(pw.pw_name, auth_cb, pcp, &ret) < 0)
return (PERM_FAIL);
- if (authlist != NULL) {
- ret = check_auth_list(pcp, authlist);
-
- if (ret != PERM_DENIED) {
- _free_user_defs(authlist, def_prof);
- return (ret);
- }
- }
-
- /*
- * Put off checking def_prof for later in an attempt to consolidate
- * prof_attr accesses.
- */
-
- uap = getusernam(pw.pw_name);
- if (uap != NULL) {
- /* Get the authorizations from user_attr. */
- userattr_authlist = kva_match(uap->attr, USERATTR_AUTHS_KW);
- if (userattr_authlist != NULL) {
- ret = check_auth_list(pcp, userattr_authlist);
- }
- }
-
- if ((ret == PERM_DENIED) && (def_prof != NULL)) {
- /* Check generic profiles. */
- ret = check_prof_list(pcp, def_prof);
- }
-
- if ((ret == PERM_DENIED) && (uap != NULL)) {
- proflist = kva_match(uap->attr, USERATTR_PROFILES_KW);
- if (proflist != NULL)
- ret = check_prof_list(pcp, proflist);
- }
-
- _free_user_defs(authlist, def_prof);
- if (uap != NULL)
- free_userattr(uap);
-
return (ret);
}
diff --git a/usr/src/cmd/truss/actions.c b/usr/src/cmd/truss/actions.c
index e04db7bdb5..2dda60fb3e 100644
--- a/usr/src/cmd/truss/actions.c
+++ b/usr/src/cmd/truss/actions.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1988 AT&T */
@@ -973,7 +972,7 @@ showargs(private_t *pri, int raw)
if (raw)
showpaths(pri, &systable[SYS_execve]);
- show_cred(pri, FALSE);
+ show_cred(pri, FALSE, FALSE);
if (aflag || eflag) { /* dump args or environment */
diff --git a/usr/src/cmd/truss/main.c b/usr/src/cmd/truss/main.c
index 736b8bc2ef..151c7492ad 100644
--- a/usr/src/cmd/truss/main.c
+++ b/usr/src/cmd/truss/main.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -47,6 +46,7 @@
#include <sys/mman.h>
#include <sys/resource.h>
#include <libproc.h>
+#include <priv.h>
#include "ramdata.h"
#include "proto.h"
#include "htbl.h"
@@ -603,7 +603,7 @@ main(int argc, char *argv[])
if (created) {
per_proc_init();
procadd(created, NULL);
- show_cred(pri, TRUE);
+ show_cred(pri, TRUE, FALSE);
} else { /* grab the specified processes */
int gotone = FALSE;
@@ -1127,6 +1127,7 @@ worker_thread(void *arg)
exit_called = TRUE;
break;
case SYS_execve:
+ show_cred(pri, FALSE, TRUE);
(void) sysentry(pri, dotrace);
if (dotrace && !cflag &&
prismember(&trace, what)) {
@@ -2307,18 +2308,31 @@ fetchstring(private_t *pri, long addr, int maxleng)
return (pri->str_buffer);
}
+static priv_set_t *
+getset(prpriv_t *p, priv_ptype_t set)
+{
+ return ((priv_set_t *)
+ &p->pr_sets[priv_getsetbyname(set) * p->pr_setsize]);
+}
+
void
-show_cred(private_t *pri, int new)
+show_cred(private_t *pri, int new, int loadonly)
{
prcred_t cred;
+ prpriv_t *privs;
if (proc_get_cred(Pstatus(Proc)->pr_pid, &cred, 0) < 0) {
- perror("show_cred()");
+ perror("show_cred() - credential");
(void) printf("%s\t*** Cannot get credentials\n", pri->pname);
return;
}
+ if ((privs = proc_get_priv(Pstatus(Proc)->pr_pid)) == NULL) {
+ perror("show_cred() - privileges");
+ (void) printf("%s\t*** Cannot get privileges\n", pri->pname);
+ return;
+ }
- if (!cflag && prismember(&trace, SYS_execve)) {
+ if (!loadonly && !cflag && prismember(&trace, SYS_execve)) {
if (new)
credentials = cred;
if ((new && cred.pr_ruid != cred.pr_suid) ||
@@ -2339,9 +2353,29 @@ show_cred(private_t *pri, int new)
(int)cred.pr_rgid,
(int)cred.pr_egid,
(int)cred.pr_sgid);
+ if (privdata != NULL && cred.pr_euid != 0) {
+ priv_set_t *npset = getset(privs, PRIV_PERMITTED);
+ priv_set_t *opset = getset(privdata, PRIV_PERMITTED);
+ char *s, *t;
+ if (!priv_issubset(npset, opset)) {
+ /* Use the to be freed privdata as scratch */
+ priv_inverse(opset);
+ priv_intersect(npset, opset);
+ s = priv_set_to_str(opset, ',', PRIV_STR_SHORT);
+ t = priv_set_to_str(npset, ',', PRIV_STR_SHORT);
+ (void) printf("%s *** FPRIV: P/E: %s ***\n",
+ pri->pname,
+ strlen(s) > strlen(t) ? t : s);
+ free(s);
+ free(t);
+ }
+ }
}
+ if (privdata != NULL)
+ free(privdata);
credentials = cred;
+ privdata = privs;
}
/*
@@ -2479,7 +2513,7 @@ grabit(private_t *pri, proc_set_t *set)
else
(void) Punsetflags(Proc, PR_FORK);
procadd(set->pid, set->lwps);
- show_cred(pri, TRUE);
+ show_cred(pri, TRUE, FALSE);
return (TRUE);
}
diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c
index 2848fd1490..c4ba8b2abd 100644
--- a/usr/src/cmd/truss/print.c
+++ b/usr/src/cmd/truss/print.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -2257,6 +2256,7 @@ prt_pfl(private_t *pri, int raw, long val)
case PRIV_AWARE: s = "PRIV_AWARE"; break;
case PRIV_XPOLICY: s = "PRIV_XPOLICY"; break;
case PRIV_AWARE_RESET: s = "PRIV_AWARE_RESET"; break;
+ case PRIV_PFEXEC: s = "PRIV_PFEXEC"; break;
case NET_MAC_AWARE: s = "NET_MAC_AWARE"; break;
case NET_MAC_AWARE_INHERIT:
s = "NET_MAC_AWARE_INHERIT";
diff --git a/usr/src/cmd/truss/proto.h b/usr/src/cmd/truss/proto.h
index 25f92cef67..670fe95f1b 100644
--- a/usr/src/cmd/truss/proto.h
+++ b/usr/src/cmd/truss/proto.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -110,7 +109,7 @@ extern int fdlist(char *, fileset_t *);
extern int liblist(char *, int);
extern char *fetchstring(private_t *, long, int);
-extern void show_cred(private_t *, int);
+extern void show_cred(private_t *, int, int);
extern void errmsg(const char *, const char *);
extern void abend(const char *, const char *);
diff --git a/usr/src/cmd/truss/ramdata.c b/usr/src/cmd/truss/ramdata.c
index bd02ab6e2a..abb8ee202b 100644
--- a/usr/src/cmd/truss/ramdata.c
+++ b/usr/src/cmd/truss/ramdata.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -52,6 +51,7 @@ uid_t Egid; /* truss's effective gid */
uid_t Ruid; /* truss's real uid */
uid_t Rgid; /* truss's real gid */
prcred_t credentials; /* traced process credentials */
+prpriv_t *privdata; /* traced process privileges */
int istty; /* TRUE iff output is a tty */
time_t starttime; /* start time */
diff --git a/usr/src/cmd/truss/ramdata.h b/usr/src/cmd/truss/ramdata.h
index ea2bbdda46..788422827e 100644
--- a/usr/src/cmd/truss/ramdata.h
+++ b/usr/src/cmd/truss/ramdata.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -136,6 +135,7 @@ extern uid_t Egid; /* truss's effective gid */
extern uid_t Ruid; /* truss's real uid */
extern uid_t Rgid; /* truss's real gid */
extern prcred_t credentials; /* traced process credentials */
+extern prpriv_t *privdata; /* traced process privileges */
extern int istty; /* TRUE iff output is a tty */
extern time_t starttime; /* start time */
diff --git a/usr/src/head/prof_attr.h b/usr/src/head/prof_attr.h
index 42ff2d8534..b1ad96e116 100644
--- a/usr/src/head/prof_attr.h
+++ b/usr/src/head/prof_attr.h
@@ -19,15 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _PROF_ATTR_H
#define _PROF_ATTR_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -50,6 +47,8 @@ extern "C" {
#define PROFATTR_COL3_KW "desc"
#define PROFATTR_COL4_KW "attr"
+#define PROFILE_STOP "Stop"
+
#define DEF_PROF "PROFS_GRANTED="
#define DEF_CONSUSER "CONSOLE_USER="
diff --git a/usr/src/head/secdb.h b/usr/src/head/secdb.h
index 105e44c8d8..be346e7e04 100644
--- a/usr/src/head/secdb.h
+++ b/usr/src/head/secdb.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SECDB_H
@@ -49,6 +48,8 @@ extern "C" {
#define KV_WILDCARD "*"
#define KV_WILDCHAR '*'
#define KV_ACTION_WILDCARD "*;*;*;*;*"
+#define KV_SEPCHAR ','
+#define KV_SEPSTR ","
#define KV_FLAG_NONE 0x0000
#define KV_FLAG_REQUIRED 0x0001
@@ -84,8 +85,12 @@ extern kva_t *_kva_dup(kva_t *);
extern void _kva_free(kva_t *);
extern kva_t *_new_kva(int size);
extern kva_t *_str2kva(char *, char *, char *);
-extern int _get_user_defs(const char *, char **, char **);
-extern void _free_user_defs(char *, char *);
+extern int _enum_auths(const char *, int (*)(const char *, void *, void *),
+ void *ctxt, void *pres);
+extern int _enum_profs(const char *,
+ int (*)(const char *, kva_t *, void *, void *), void *ctxt, void *pres);
+extern int _enum_attrs(const char *,
+ int (*)(const char *, kva_t *, void *, void *), void *ctxt, void *pres);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libbsm/audit_event.txt b/usr/src/lib/libbsm/audit_event.txt
index 8ee50ca320..06aa34a2fa 100644
--- a/usr/src/lib/libbsm/audit_event.txt
+++ b/usr/src/lib/libbsm/audit_event.txt
@@ -1,6 +1,5 @@
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
#
#
# CDDL HEADER START
@@ -183,6 +182,7 @@
113:AUE_SYSTEMBOOT:system booted:na
114:AUE_ASYNC_DAEMON_EXIT:async_daemon(2) exited:no
115:AUE_NFSSVC_EXIT:nfssvc(2) exited:no
+116:AUE_PFEXEC:execve(2) with pfexec enabled:ps,ex,ua,as
130:AUE_GETAUID:getauid(2):aa
131:AUE_SETAUID:setauid(2):aa
132:AUE_GETAUDIT:getaudit(2):aa
diff --git a/usr/src/lib/libc/port/gen/getusershell.c b/usr/src/lib/libc/port/gen/getusershell.c
index 368fa72a61..df10f2f6fd 100644
--- a/usr/src/lib/libc/port/gen/getusershell.c
+++ b/usr/src/lib/libc/port/gen/getusershell.c
@@ -1,6 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -12,8 +11,6 @@
* specifies the terms and conditions for redistribution.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "lint.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -56,16 +53,25 @@ const char *okshells[] = {
"/usr/bin/pfsh",
"/usr/bin/pfcsh",
"/usr/bin/pfksh",
+ "/usr/bin/pfksh93",
"/usr/bin/bash",
"/usr/bin/tcsh",
"/usr/bin/zsh",
+ "/usr/bin/pfbash",
+ "/usr/bin/pftcsh",
+ "/usr/bin/pfzsh",
"/bin/pfsh",
"/bin/pfcsh",
"/bin/pfksh",
+ "/bin/pfksh93",
"/bin/bash",
"/bin/tcsh",
"/bin/zsh",
+ "/bin/pfbash",
+ "/bin/pftcsh",
+ "/bin/pfzsh",
"/usr/xpg4/bin/sh",
+ "/usr/xpg4/bin/pfsh",
"/sbin/pfsh",
"/usr/sfw/bin/zsh",
NULL
diff --git a/usr/src/lib/libc/port/gen/privlib.c b/usr/src/lib/libc/port/gen/privlib.c
index aecb11c3b4..b490434997 100644
--- a/usr/src/lib/libc/port/gen/privlib.c
+++ b/usr/src/lib/libc/port/gen/privlib.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#pragma weak _getprivimplinfo = getprivimplinfo
@@ -871,11 +870,7 @@ priv_emptyset(priv_set_t *set)
void
priv_basicset(priv_set_t *set)
{
- priv_data_t *d;
-
- LOADPRIVDATA(d);
-
- priv_copyset(d->pd_basicset, set);
+ priv_copyset(priv_basic(), set);
}
void
diff --git a/usr/src/lib/libsecdb/common/chkauthattr.c b/usr/src/lib/libsecdb/common/chkauthattr.c
index e5f0093342..7f8be5aa4d 100644
--- a/usr/src/lib/libsecdb/common/chkauthattr.c
+++ b/usr/src/lib/libsecdb/common/chkauthattr.c
@@ -22,14 +22,11 @@
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+#include <alloca.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <limits.h>
#include <pwd.h>
#include <nss_dbdefs.h>
#include <deflt.h>
@@ -37,115 +34,261 @@
#include <prof_attr.h>
#include <user_attr.h>
+#define COPYTOSTACK(dst, csrc) { \
+ size_t len = strlen(csrc) + 1; \
+ dst = alloca(len); \
+ (void) memcpy(dst, csrc, len); \
+ }
+
+static kva_t *get_default_attrs(const char *);
+static void free_default_attrs(kva_t *);
+
+/*
+ * Enumeration functions for auths and profiles; the enumeration functions
+ * take a callback with four arguments:
+ * const char * profile name (or NULL unless wantattr is false)
+ * kva_t * attributes (or NULL unless wantattr is true)
+ * void * context
+ * void * pointer to the result
+ * When the call back returns non-zero, the enumeration ends.
+ * The function might be NULL but only for profiles as we are always collecting
+ * all the profiles.
+ * Both the auths and the profiles arguments may be NULL.
+ *
+ * These should be the only implementation of the algorithm of "finding me
+ * all the profiles/athorizations/keywords/etc.
+ */
-static int _is_authorized(const char *, char *);
-static int _chk_policy_auth(const char *, const char *, char **, int *);
-static int _chkprof_for_auth(const char *, const char *, char **, int *);
+#define CONSUSER_PROFILE_KW "consprofile"
+#define DEF_LOCK_AFTER_RETRIES "LOCK_AFTER_RETRIES="
+
+static struct dfltplcy {
+ char *attr;
+ const char *defkw;
+} dfltply[] = {
+ /* CONSUSER MUST BE FIRST! */
+ { CONSUSER_PROFILE_KW, DEF_CONSUSER},
+ { PROFATTR_AUTHS_KW, DEF_AUTH},
+ { PROFATTR_PROFS_KW, DEF_PROF},
+ { USERATTR_LIMPRIV_KW, DEF_LIMITPRIV},
+ { USERATTR_DFLTPRIV_KW, DEF_DFLTPRIV},
+ { USERATTR_LOCK_AFTER_RETRIES_KW, DEF_LOCK_AFTER_RETRIES}
+};
+
+#define NDFLTPLY (sizeof (dfltply)/sizeof (struct dfltplcy))
+#define GETCONSPROF(a) (kva_match((a), CONSUSER_PROFILE_KW))
+#define GETPROF(a) (kva_match((a), PROFATTR_PROFS_KW))
+
+/*
+ * Enumerate profiles from listed profiles.
+ */
int
-chkauthattr(const char *authname, const char *username)
+_enum_common_p(const char *cprofiles,
+ int (*cb)(const char *, kva_t *, void *, void *),
+ void *ctxt, void *pres, boolean_t wantattr,
+ int *pcnt, char *profs[MAXPROFS])
{
- int auth_granted = 0;
- char *auths;
- char *profiles;
- userattr_t *user = NULL;
- char *chkedprof[MAXPROFS];
- int chkedprof_cnt = 0;
- int i;
+ char *prof, *last;
+ char *profiles;
+ profattr_t *pa;
+ int i;
+ int res = 0;
- if (authname == NULL || username == NULL)
+ if (cprofiles == NULL)
return (0);
- /* Check against AUTHS_GRANTED and PROFS_GRANTED in policy.conf */
- auth_granted = _chk_policy_auth(authname, username, chkedprof,
- &chkedprof_cnt);
- if (auth_granted)
- goto exit;
+ if (*pcnt > 0 && strcmp(profs[*pcnt - 1], PROFILE_STOP) == NULL)
+ return (0);
- if ((user = getusernam(username)) == NULL)
- goto exit;
+ COPYTOSTACK(profiles, cprofiles)
- /* Check against authorizations listed in user_attr */
- if ((auths = kva_match(user->attr, USERATTR_AUTHS_KW)) != NULL) {
- auth_granted = _is_authorized(authname, auths);
- if (auth_granted)
- goto exit;
- }
+ while (prof = strtok_r(profiles, KV_SEPSTR, &last)) {
- /* Check against authorizations specified by profiles */
- if ((profiles = kva_match(user->attr, USERATTR_PROFILES_KW)) != NULL)
- auth_granted = _chkprof_for_auth(profiles, authname,
- chkedprof, &chkedprof_cnt);
+ profiles = NULL; /* For next iterations of strtok_r */
-exit:
- /* free memory allocated for checked array */
- for (i = 0; i < chkedprof_cnt; i++) {
- free(chkedprof[i]);
- }
+ for (i = 0; i < *pcnt; i++)
+ if (strcmp(profs[i], prof) == 0)
+ goto cont;
- if (user != NULL)
- free_userattr(user);
+ if (*pcnt >= MAXPROFS) /* oops: too many profs */
+ return (-1);
- return (auth_granted);
+ /* Add it */
+ profs[(*pcnt)++] = strdup(prof);
+
+ if (strcmp(profs[*pcnt - 1], PROFILE_STOP) == 0)
+ break;
+
+ /* find the profiles for this profile */
+ pa = getprofnam(prof);
+
+ if (cb != NULL && (!wantattr || pa != NULL && pa->attr != NULL))
+ res = cb(prof, pa ? pa->attr : NULL, ctxt, pres);
+
+ if (pa != NULL) {
+ if (res == 0 && pa->attr != NULL) {
+ res = _enum_common_p(GETPROF(pa->attr), cb,
+ ctxt, pres, wantattr, pcnt, profs);
+ }
+ free_profattr(pa);
+ }
+ if (res != 0)
+ return (res);
+cont:
+ continue;
+ }
+ return (res);
}
+/*
+ * Enumerate all attributes associated with a username and the profiles
+ * associated with the user.
+ */
static int
-_chkprof_for_auth(const char *profs, const char *authname,
- char **chkedprof, int *chkedprof_cnt)
+_enum_common(const char *username,
+ int (*cb)(const char *, kva_t *, void *, void *),
+ void *ctxt, void *pres, boolean_t wantattr)
{
+ userattr_t *ua;
+ int res = 0;
+ int cnt = 0;
+ char *profs[MAXPROFS];
+ kva_t *kattrs;
- char *prof, *lasts, *auths, *profiles;
- profattr_t *pa;
- int i;
- int checked = 0;
+ if (cb == NULL)
+ return (-1);
- for (prof = strtok_r((char *)profs, ",", &lasts); prof != NULL;
- prof = strtok_r(NULL, ",", &lasts)) {
+ ua = getusernam(username);
- checked = 0;
- /* check if this profile has been checked */
- for (i = 0; i < *chkedprof_cnt; i++) {
- if (strcmp(chkedprof[i], prof) == 0) {
- checked = 1;
- break;
+ if (ua != NULL) {
+ if (ua->attr != NULL) {
+ if (wantattr)
+ res = cb(NULL, ua->attr, ctxt, pres);
+ if (res == 0) {
+ res = _enum_common_p(GETPROF(ua->attr),
+ cb, ctxt, pres, wantattr, &cnt, profs);
}
}
+ free_userattr(ua);
+ if (res != 0)
+ return (res);
+ }
- if (!checked) {
-
- chkedprof[*chkedprof_cnt] = strdup(prof);
- *chkedprof_cnt = *chkedprof_cnt + 1;
+ if ((cnt == 0 || strcmp(profs[cnt-1], PROFILE_STOP) != 0) &&
+ (kattrs = get_default_attrs(username)) != NULL) {
- if ((pa = getprofnam(prof)) == NULL)
- continue;
+ res = _enum_common_p(GETCONSPROF(kattrs), cb, ctxt, pres,
+ wantattr, &cnt, profs);
- if ((auths = kva_match(pa->attr,
- PROFATTR_AUTHS_KW)) != NULL) {
- if (_is_authorized(authname, auths)) {
- free_profattr(pa);
- return (1);
- }
- }
- if ((profiles =
- kva_match(pa->attr, PROFATTR_PROFS_KW)) != NULL) {
- /* Check for authorization in subprofiles */
- if (_chkprof_for_auth(profiles, authname,
- chkedprof, chkedprof_cnt)) {
- free_profattr(pa);
- return (1);
- }
- }
- free_profattr(pa);
+ if (res == 0) {
+ res = _enum_common_p(GETPROF(kattrs), cb, ctxt, pres,
+ wantattr, &cnt, profs);
}
+
+ if (res == 0 && wantattr)
+ res = cb(NULL, kattrs, ctxt, pres);
+
+ free_default_attrs(kattrs);
}
- /* authorization not found in any profile */
- return (0);
+
+ free_proflist(profs, cnt);
+
+ return (res);
+}
+
+/*
+ * Enumerate profiles with a username argument.
+ */
+int
+_enum_profs(const char *username,
+ int (*cb)(const char *, kva_t *, void *, void *),
+ void *ctxt, void *pres)
+{
+ return (_enum_common(username, cb, ctxt, pres, B_FALSE));
+}
+
+/*
+ * Enumerate attributes with a username argument.
+ */
+int
+_enum_attrs(const char *username,
+ int (*cb)(const char *, kva_t *, void *, void *),
+ void *ctxt, void *pres)
+{
+ return (_enum_common(username, cb, ctxt, pres, B_TRUE));
+}
+
+
+/*
+ * Enumerate authorizations in the "auths" argument.
+ */
+static int
+_enum_auths_a(const char *cauths, int (*cb)(const char *, void *, void *),
+ void *ctxt, void *pres)
+{
+ char *auth, *last, *auths;
+ int res = 0;
+
+ if (cauths == NULL || cb == NULL)
+ return (0);
+
+ COPYTOSTACK(auths, cauths)
+
+ while (auth = strtok_r(auths, KV_SEPSTR, &last)) {
+ auths = NULL; /* For next iterations of strtok_r */
+
+ res = cb(auth, ctxt, pres);
+
+ if (res != 0)
+ return (res);
+ }
+ return (res);
+}
+
+/*
+ * Magic struct and function to allow using the _enum_attrs functions to
+ * enumerate the authorizations.
+ */
+typedef struct ccomm2auth {
+ int (*cb)(const char *, void *, void *);
+ void *ctxt;
+} ccomm2auth;
+
+/*ARGSUSED*/
+static int
+comm2auth(const char *name, kva_t *attr, void *ctxt, void *pres)
+{
+ ccomm2auth *ca = ctxt;
+ char *auths;
+
+ /* Note: PROFATTR_AUTHS_KW is equal to USERATTR_AUTHS_KW */
+ auths = kva_match(attr, PROFATTR_AUTHS_KW);
+ return (_enum_auths_a(auths, ca->cb, ca->ctxt, pres));
+}
+
+/*
+ * Enumerate authorizations for username.
+ */
+int
+_enum_auths(const char *username,
+ int (*cb)(const char *, void *, void *),
+ void *ctxt, void *pres)
+{
+ ccomm2auth c2a;
+
+ if (cb == NULL)
+ return (-1);
+
+ c2a.cb = cb;
+ c2a.ctxt = ctxt;
+
+ return (_enum_common(username, comm2auth, &c2a, pres, B_TRUE));
}
int
_auth_match(const char *pattern, const char *auth)
{
size_t len;
- char wildcard = KV_WILDCHAR;
char *grant;
len = strlen(pattern);
@@ -154,7 +297,7 @@ _auth_match(const char *pattern, const char *auth)
* If the wildcard is not in the last position in the string, don't
* match against it.
*/
- if (pattern[len-1] != wildcard)
+ if (pattern[len-1] != KV_WILDCHAR)
return (0);
/*
@@ -173,66 +316,32 @@ _auth_match(const char *pattern, const char *auth)
}
static int
-_is_authorized(const char *authname, char *auths)
+_is_authorized(const char *auth, void *authname, void *res)
{
- int found = 0; /* have we got a match, yet */
- char wildcard = '*';
- char *auth; /* current authorization being compared */
- char *buf;
- char *lasts;
-
- buf = strdup(auths);
- for (auth = strtok_r(auths, ",", &lasts); auth != NULL && !found;
- auth = strtok_r(NULL, ",", &lasts)) {
- if (strcmp((char *)authname, auth) == 0) {
- /* Exact match. We're done. */
- found = 1;
- } else if (strchr(auth, wildcard) != NULL) {
- if (_auth_match(auth, authname)) {
- found = 1;
- break;
- }
- }
- }
+ int *resp = res;
- free(buf);
+ if (strcmp(authname, auth) == 0 ||
+ (strchr(auth, KV_WILDCHAR) != NULL &&
+ _auth_match(auth, authname))) {
+ *resp = 1;
+ return (1);
+ }
- return (found);
+ return (0);
}
-
-/*
- * read /etc/security/policy.conf for AUTHS_GRANTED.
- * return 1 if found matching authname.
- * Otherwise, read PROFS_GRANTED to see if authname exists in any
- * default profiles.
- */
-static int
-_chk_policy_auth(const char *authname, const char *username, char **chkedprof,
- int *chkedprof_cnt)
+int
+chkauthattr(const char *authname, const char *username)
{
- char *auths = NULL;
- char *profs = NULL;
- int ret = 1;
+ int auth_granted = 0;
- if (_get_user_defs(username, &auths, &profs) != 0)
+ if (authname == NULL || username == NULL)
return (0);
- if (auths != NULL) {
- if (_is_authorized(authname, auths))
- goto exit;
- }
-
- if (profs != NULL) {
- if (_chkprof_for_auth(profs, authname, chkedprof,
- chkedprof_cnt))
- goto exit;
- }
- ret = 0;
+ (void) _enum_auths(username, _is_authorized, (char *)authname,
+ &auth_granted);
-exit:
- _free_user_defs(auths, profs);
- return (ret);
+ return (auth_granted);
}
#define CONSOLE_USER_LINK "/dev/vt/console_user"
@@ -257,77 +366,58 @@ is_cons_user(const char *user)
return (pw.pw_uid == cons.st_uid);
}
+static void
+free_default_attrs(kva_t *kva)
+{
+ int i;
+
+ for (i = 0; i < kva->length; i++)
+ free(kva->data[i].value);
-int
-_get_user_defs(const char *user, char **def_auth, char **def_prof)
+ free(kva);
+}
+
+/*
+ * Return the default attributes; this are ignored when a STOP profile
+ * was found.
+ */
+static kva_t *
+get_default_attrs(const char *user)
{
- char *cp;
- char *profs;
- void *defp;
+ void *defp;
+ kva_t *kva;
+ int i;
- if ((defp = defopen_r(AUTH_POLICY)) == NULL) {
- if (def_auth != NULL) {
- *def_auth = NULL;
- }
- if (def_prof != NULL) {
- *def_prof = NULL;
- }
- return (-1);
- }
+ kva = malloc(sizeof (kva_t) + sizeof (kv_t) * NDFLTPLY);
- if (def_auth != NULL) {
- if ((cp = defread_r(DEF_AUTH, defp)) != NULL) {
- if ((*def_auth = strdup(cp)) == NULL) {
- defclose_r(defp);
- return (-1);
- }
- } else {
- *def_auth = NULL;
- }
- }
- if (def_prof != NULL) {
- if (is_cons_user(user) &&
- (cp = defread_r(DEF_CONSUSER, defp)) != NULL) {
- if ((*def_prof = strdup(cp)) == NULL) {
- defclose_r(defp);
- return (-1);
- }
- }
- if ((cp = defread_r(DEF_PROF, defp)) != NULL) {
- int prof_len;
-
- if (*def_prof == NULL) {
- if ((*def_prof = strdup(cp)) == NULL) {
- defclose_r(defp);
- return (-1);
- }
- defclose_r(defp);
- return (0);
- }
+ if (kva == NULL)
+ return (NULL);
- /* concatenate def profs with "," separator */
- prof_len = strlen(*def_prof) + strlen(cp) + 2;
- if ((profs = malloc(prof_len)) == NULL) {
- free(*def_prof);
- *def_prof = NULL;
- defclose_r(defp);
- return (-1);
- }
- (void) snprintf(profs, prof_len, "%s,%s", *def_prof,
- cp);
- free(*def_prof);
- *def_prof = profs;
- }
+ kva->data = (kv_t *)(void *)&kva[1];
+ kva->length = 0;
+
+ if ((defp = defopen_r(AUTH_POLICY)) == NULL)
+ goto return_null;
+
+ for (i = is_cons_user(user) ? 0 : 1; i < NDFLTPLY; i++) {
+ char *cp = defread_r(dfltply[i].defkw, defp);
+
+ if (cp == NULL)
+ continue;
+ if ((cp = strdup(cp)) == NULL)
+ goto return_null;
+
+ kva->data[kva->length].key = dfltply[i].attr;
+ kva->data[kva->length++].value = cp;
}
- defclose_r(defp);
- return (0);
-}
+ (void) defclose_r(defp);
+ return (kva);
+return_null:
+ if (defp != NULL)
+ (void) defclose_r(defp);
-void
-_free_user_defs(char *def_auth, char *def_prof)
-{
- free(def_auth);
- free(def_prof);
+ free_default_attrs(kva);
+ return (NULL);
}
diff --git a/usr/src/lib/libsecdb/common/getexecattr.c b/usr/src/lib/libsecdb/common/getexecattr.c
index b6ffb1dab3..f4c48f1023 100644
--- a/usr/src/lib/libsecdb/common/getexecattr.c
+++ b/usr/src/lib/libsecdb/common/getexecattr.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -220,88 +219,68 @@ free_execattr(execattr_t *exec)
}
}
+typedef struct call {
+ const char *type;
+ const char *id;
+ int sflag;
+} call;
+
+typedef struct result {
+ execattr_t *head;
+ execattr_t *prev;
+} result;
+
+/*ARGSUSED*/
+static int
+findexecattr(const char *prof, kva_t *kva, void *ctxt, void *res)
+{
+ execattr_t *exec;
+ call *c = ctxt;
+ result *r = res;
+
+ if ((exec = getexecprof(prof, c->type, c->id, c->sflag)) != NULL) {
+ if (IS_GET_ONE(c->sflag)) {
+ r->head = exec;
+ return (1);
+ } else if (IS_GET_ALL(c->sflag)) {
+ if (r->head == NULL) {
+ r->head = exec;
+ r->prev = get_tail(r->head);
+ } else {
+ r->prev->next = exec;
+ r->prev = get_tail(exec);
+ }
+ }
+ }
+ return (0);
+}
+
static execattr_t *
userprof(const char *username, const char *type, const char *id,
int search_flag)
{
- int err = 0;
- char *last;
- char *sep = ",";
- char *proflist = NULL;
- char *profname = NULL;
- char buf[NSS_BUFLEN_USERATTR];
char pwdb[NSS_BUFLEN_PASSWD];
- kva_t *user_attr;
- userstr_t user;
- userstr_t *utmp;
- execattr_t *exec;
- execattr_t *head = NULL;
- execattr_t *prev = NULL;
struct passwd pwd;
-
- char *profArray[MAXPROFS];
- int profcnt = 0;
- int i;
+ call call;
+ result result;
/*
* Check if specified username is valid user
*/
if (getpwnam_r(username, &pwd, pwdb, sizeof (pwdb)) == NULL) {
- return (head);
+ return (NULL);
}
- utmp = _getusernam(username, &user, buf, NSS_BUFLEN_USERATTR, &err);
- if (utmp != NULL) {
- user_attr = _str2kva(user.attr, KV_ASSIGN, KV_DELIMITER);
- if ((proflist = kva_match(user_attr, "profiles")) != NULL) {
- /* Get the list of profiles for this user */
- for (profname = _strtok_escape(proflist, sep, &last);
- profname != NULL;
- profname = _strtok_escape(NULL, sep, &last)) {
- getproflist(profname, profArray, &profcnt);
- }
- }
- }
+ result.head = result.prev = NULL;
+ call.type = type;
+ call.id = id;
+ call.sflag = search_flag;
- /* Get the list of default profiles */
- proflist = NULL;
- (void) _get_user_defs(username, NULL, &proflist);
- if (proflist != NULL) {
- for (profname = _strtok_escape(proflist, sep, &last);
- profname != NULL;
- profname = _strtok_escape(NULL, sep, &last)) {
- getproflist(profname, profArray, &profcnt);
- }
- _free_user_defs(NULL, proflist);
- }
+ (void) _enum_profs(username, findexecattr, &call, &result);
- if (profcnt == 0) {
- return (head);
- }
-
- /* Get execs from the list of profiles */
- for (i = 0; i < profcnt; i++) {
- profname = profArray[i];
- if ((exec = getexecprof(profname, type, id, search_flag)) !=
- NULL) {
- if (IS_GET_ONE(search_flag)) {
- head = exec;
- break;
- } else if (IS_GET_ALL(search_flag)) {
- if (head == NULL) {
- head = exec;
- prev = get_tail(head);
- } else {
- prev->next = exec;
- prev = get_tail(exec);
- }
- }
- }
- }
- free_proflist(profArray, profcnt);
- return (head);
+ return (result.head);
}
diff --git a/usr/src/lib/libsecdb/common/getprofattr.c b/usr/src/lib/libsecdb/common/getprofattr.c
index bb3173672c..ac9b9b0c36 100644
--- a/usr/src/lib/libsecdb/common/getprofattr.c
+++ b/usr/src/lib/libsecdb/common/getprofattr.c
@@ -19,12 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
@@ -121,6 +118,9 @@ profstr2attr(profstr_t *prof)
}
+extern int _enum_common_p(const char *, int (*)(const char *, kva_t *, void *,
+ void *), void *, void *, boolean_t, int *, char *[MAXPROFS]);
+
/*
* Given a profile name, gets the list of profiles found from
* the whole hierarchy, using the given profile as root
@@ -128,44 +128,12 @@ profstr2attr(profstr_t *prof)
void
getproflist(const char *profileName, char **profArray, int *profcnt)
{
- profattr_t *profattr;
- char *subprofiles, *lasts, *profname;
- int i;
-
- /* Check if this is a duplicate */
- for (i = 0; i < *profcnt; i++) {
- if (strcmp(profileName, profArray[i]) == 0) {
- /* It's a duplicate, don't need to do anything */
- return;
- }
- }
-
- profArray[*profcnt] = strdup(profileName);
- *profcnt = *profcnt + 1;
-
- profattr = getprofnam(profileName);
- if (profattr == NULL) {
+ /* There can't be a "," in a profile name. */
+ if (strchr(profileName, KV_SEPCHAR) != NULL)
return;
- }
- if (profattr->attr == NULL) {
- free_profattr(profattr);
- return;
- }
-
- subprofiles = kva_match(profattr->attr, PROFATTR_PROFS_KW);
- if (subprofiles == NULL) {
- free_profattr(profattr);
- return;
- }
-
- /* get execattr from each subprofiles */
- for (profname = (char *)strtok_r(subprofiles, ",", &lasts);
- profname != NULL;
- profname = (char *)strtok_r(NULL, ",", &lasts)) {
- getproflist(profname, profArray, profcnt);
- }
- free_profattr(profattr);
+ (void) _enum_common_p(profileName, NULL, NULL, NULL, B_FALSE,
+ profcnt, profArray);
}
void
diff --git a/usr/src/lib/libsecdb/common/mapfile-vers b/usr/src/lib/libsecdb/common/mapfile-vers
index 1b85f8324d..87d4e1ada5 100644
--- a/usr/src/lib/libsecdb/common/mapfile-vers
+++ b/usr/src/lib/libsecdb/common/mapfile-vers
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -76,14 +75,15 @@ SUNWprivate_1.1 {
_csl_to_argv;
_do_unescape;
_free_argv;
- _free_user_defs;
- _get_user_defs;
_insert2kva;
_kva2str;
_kva_dup;
_kva_free;
_new_kva;
_str2kva;
+ _enum_profs;
+ _enum_auths;
+ _enum_attrs;
local:
*;
};
diff --git a/usr/src/lib/libsecdb/exec_attr.txt b/usr/src/lib/libsecdb/exec_attr.txt
index f4f302987e..f9c90e41d0 100644
--- a/usr/src/lib/libsecdb/exec_attr.txt
+++ b/usr/src/lib/libsecdb/exec_attr.txt
@@ -20,7 +20,6 @@
#
# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
-
#
# /etc/security/exec_attr
#
@@ -110,6 +109,25 @@ File System Management:suser:cmd:::/usr/sbin/umount:uid=0
File System Management:suser:cmd:::/usr/sbin/umountall:uid=0
File System Management:suser:cmd:::/usr/sbin/unshare:uid=0;gid=root
File System Management:suser:cmd:::/usr/sbin/unshareall:uid=0;gid=root
+Forced Privilege:solaris:cmd:::/usr/bin/newtask:\
+ privs=proc_taskid,sys_resource,sys_res_config,proc_priocntl
+Forced Privilege:solaris:cmd:::/usr/bin/rcp:privs=net_privaddr
+Forced Privilege:solaris:cmd:::/usr/bin/rdist:privs=net_privaddr
+Forced Privilege:solaris:cmd:::/usr/bin/rlogin:privs=net_privaddr
+Forced Privilege:solaris:cmd:::/usr/bin/rmformat:\
+ privs=file_dac_read,file_dac_write,proc_fork,proc_exec,sys_mount,sys_devices
+Forced Privilege:solaris:cmd:::/usr/bin/rsh:privs=net_privaddr
+Forced Privilege:solaris:cmd:::/usr/bin/w:privs=proc_owner
+Forced Privilege:solaris:cmd:::/usr/lib/fs/ufs/quota:privs=file_dac_read
+Forced Privilege:solaris:cmd:::/usr/lib/fs/ufs/ufsdump:privs=net_privaddr
+Forced Privilege:solaris:cmd:::/usr/lib/fs/ufs/ufsrestore:privs=net_privaddr
+Forced Privilege:solaris:cmd:::/usr/sbin/ping:\
+ privs=net_icmpaccess,sys_ip_config
+Forced Privilege:solaris:cmd:::/usr/sbin/traceroute:\
+ privs=net_icmpaccess,net_rawaccess
+Forced Privilege:solaris:cmd:::/usr/sbin/whodo:privs=proc_owner
+Forced Privilege:solaris:cmd:::/usr/lib/fs/smbfs/mount:privs=sys_mount
+Forced Privilege:solaris:cmd:::/usr/lib/fs/smbfs/umount:privs=sys_mount
IP Filter Management:solaris:cmd:::/usr/sbin/ipf:privs=sys_ip_config
IP Filter Management:solaris:cmd:::/usr/sbin/ipfs:privs=sys_ip_config
IP Filter Management:solaris:cmd:::/usr/sbin/ipmon:privs=sys_ip_config
diff --git a/usr/src/lib/libsecdb/help/profiles/Makefile b/usr/src/lib/libsecdb/help/profiles/Makefile
index d3e01a790c..e34952fc27 100644
--- a/usr/src/lib/libsecdb/help/profiles/Makefile
+++ b/usr/src/lib/libsecdb/help/profiles/Makefile
@@ -73,6 +73,7 @@ HTMLENTS = \
RtPrntAdmin.html \
RtProcManagement.html \
RtReparseMngmnt.html \
+ RtReservedProfile.html \
RtRightsDelegate.html \
RtSMBMngmnt.html \
RtSMBFSMngmnt.html \
diff --git a/usr/src/lib/libsecdb/help/profiles/RtReservedProfile.html b/usr/src/lib/libsecdb/help/profiles/RtReservedProfile.html
new file mode 100644
index 0000000000..d32f69608c
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/profiles/RtReservedProfile.html
@@ -0,0 +1,35 @@
+<HTML>
+<!--
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+-->
+<HEAD>
+ <TITLE> </TITLE>
+
+
+</HEAD>
+<BODY>
+
+<p>
+This is a reserved profile. Do not assign to users or roles.
+
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/prof_attr.txt b/usr/src/lib/libsecdb/prof_attr.txt
index 8657bd40ac..3069b9bafe 100644
--- a/usr/src/lib/libsecdb/prof_attr.txt
+++ b/usr/src/lib/libsecdb/prof_attr.txt
@@ -44,6 +44,7 @@ Extended Accounting Task Management:::Manage the Task Extended Accounting servic
Extended Accounting Net Management:::Manage the Net Extended Accounting service:auths=solaris.smf.manage.extended-accounting.net,solaris.smf.value.extended-accounting.net;profiles=acctadm;help=RtExActtNet.html
File System Management:::Manage, mount, share file systems:profiles=SMB Management,VSCAN Management,SMBFS Management;auths=solaris.smf.manage.autofs,solaris.smf.manage.shares.*,solaris.smf.value.shares.*;help=RtFileSysMngmnt.html
File System Security:::Manage file system security attributes:help=RtFileSysSecurity.html
+Forced Privilege:::Commands with forced privileges associated with them:help=RtReservedProfile.html
HAL Management:::Manage HAL SMF service:auths=solaris.smf.manage.hal;help=RtHALMngmnt.html
Hotplug Management:::Manage Hotplug Connections:auths=solaris.smf.manage.hotplug,solaris.hotplug.*;help=RtHotplugMgmt.html
Idmap Name Mapping Management:::Manage Name-based Mapping Rules of Identity Mapping Service:auths=solaris.admin.idmap.rules;help=RtIdmapNameRulesMngmnt.html
@@ -78,6 +79,7 @@ Rmvolmgr Management:::Manage Removable Volume Manager SMF service:auths=solaris.
Service Management:::Manage services:auths=solaris.smf.manage,solaris.smf.modify
Service Operator:::Administer services:auths=solaris.smf.manage,solaris.smf.modify.framework
Software Installation:::Add application software to the system:help=RtSoftwareInstall.html
+Stop:::Last Profile evaluated, default profiles are not considered:help=RtReservedProfile.html
System Administrator:::Can perform most non-security administrative tasks:profiles=Audit Review,Printer Management,Cron Management,Device Management,File System Management,Mail Management,Maintenance and Repair,Media Backup,Media Restore,Name Service Management,Network Management,Object Access Management,Process Management,Software Installation,User Management,Project Management,All;help=RtSysAdmin.html
System Event Management:::Manage system events and system event channels:help=RtSysEvMngmnt.html
User Management:::Manage users, groups, home directory:auths=solaris.profmgr.read;help=RtUserMngmnt.html
diff --git a/usr/src/lib/libshell/Makefile.com b/usr/src/lib/libshell/Makefile.com
index 1e76e04af0..32bba5796e 100644
--- a/usr/src/lib/libshell/Makefile.com
+++ b/usr/src/lib/libshell/Makefile.com
@@ -20,8 +20,7 @@
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
SHELL=/usr/bin/ksh93
@@ -131,7 +130,6 @@ LDLIBS += \
-ldll \
-last \
-lsocket \
- -lsecdb \
-lm \
-lc
diff --git a/usr/src/lib/libshell/amd64/src/cmd/ksh93/FEATURE/options b/usr/src/lib/libshell/amd64/src/cmd/ksh93/FEATURE/options
index 9d0e8e990a..1db7ff29eb 100644
--- a/usr/src/lib/libshell/amd64/src/cmd/ksh93/FEATURE/options
+++ b/usr/src/lib/libshell/amd64/src/cmd/ksh93/FEATURE/options
@@ -12,9 +12,7 @@
#ifndef SHOPT_DEVFD
# define SHOPT_DEVFD 1
#endif
-#ifndef SHOPT_PFSH
-# define SHOPT_PFSH 1
-#endif
+#undef SHOPT_PFSH
#undef SHOPT_TEST_L
#ifndef SHOPT_SYSRC
# define SHOPT_SYSRC 1
diff --git a/usr/src/lib/libshell/i386/src/cmd/ksh93/FEATURE/options b/usr/src/lib/libshell/i386/src/cmd/ksh93/FEATURE/options
index 0ca0c8c236..a17b564638 100644
--- a/usr/src/lib/libshell/i386/src/cmd/ksh93/FEATURE/options
+++ b/usr/src/lib/libshell/i386/src/cmd/ksh93/FEATURE/options
@@ -12,9 +12,7 @@
#ifndef SHOPT_DEVFD
# define SHOPT_DEVFD 1
#endif
-#ifndef SHOPT_PFSH
-# define SHOPT_PFSH 1
-#endif
+#undef SHOPT_PFSH
#undef SHOPT_TEST_L
#ifndef SHOPT_SYSRC
# define SHOPT_SYSRC 1
diff --git a/usr/src/lib/libshell/sparc/src/cmd/ksh93/FEATURE/options b/usr/src/lib/libshell/sparc/src/cmd/ksh93/FEATURE/options
index 8bace0bf6b..ad28f7a1fe 100644
--- a/usr/src/lib/libshell/sparc/src/cmd/ksh93/FEATURE/options
+++ b/usr/src/lib/libshell/sparc/src/cmd/ksh93/FEATURE/options
@@ -12,9 +12,7 @@
#ifndef SHOPT_DEVFD
# define SHOPT_DEVFD 1
#endif
-#ifndef SHOPT_PFSH
-# define SHOPT_PFSH 1
-#endif
+#undef SHOPT_PFSH
#undef SHOPT_TEST_L
#ifndef SHOPT_SYSRC
# define SHOPT_SYSRC 1
diff --git a/usr/src/lib/libshell/sparcv9/src/cmd/ksh93/FEATURE/options b/usr/src/lib/libshell/sparcv9/src/cmd/ksh93/FEATURE/options
index f794aeade3..d5d031e0ec 100644
--- a/usr/src/lib/libshell/sparcv9/src/cmd/ksh93/FEATURE/options
+++ b/usr/src/lib/libshell/sparcv9/src/cmd/ksh93/FEATURE/options
@@ -12,9 +12,7 @@
#ifndef SHOPT_DEVFD
# define SHOPT_DEVFD 1
#endif
-#ifndef SHOPT_PFSH
-# define SHOPT_PFSH 1
-#endif
+#undef SHOPT_PFSH
#undef SHOPT_TEST_L
#ifndef SHOPT_SYSRC
# define SHOPT_SYSRC 1
diff --git a/usr/src/lib/pam_modules/unix_cred/unix_cred.c b/usr/src/lib/pam_modules/unix_cred/unix_cred.c
index c7c35c70a7..fcaeecb320 100644
--- a/usr/src/lib/pam_modules/unix_cred/unix_cred.c
+++ b/usr/src/lib/pam_modules/unix_cred/unix_cred.c
@@ -75,21 +75,17 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
}
/*
- * Obtain a privilege set "keyname" from userattr; if none is present,
- * fall back to the default, "defname".
+ * Set the privilege set. The attributes are enumerated by _enum_attrs,
+ * including the attribues user_attr, prof_attr and policy.conf
*/
static int
-getset(char *keyname, char *defname, userattr_t *ua, priv_set_t **res,
- void *defp)
+getset(char *str, priv_set_t **res)
{
- char *str;
priv_set_t *tmp;
char *badp;
int len;
- if ((ua == NULL || ua->attr == NULL ||
- (str = kva_match(ua->attr, keyname)) == NULL) &&
- (defp == NULL || (str = defread_r(defname, defp)) == NULL))
+ if (str == NULL)
return (0);
len = strlen(str) + 1;
@@ -129,6 +125,31 @@ getset(char *keyname, char *defname, userattr_t *ua, priv_set_t **res,
return (0);
}
+typedef struct deflim {
+ char *def;
+ char *lim;
+} deflim_t;
+
+/*ARGSUSED*/
+static int
+finddeflim(const char *name, kva_t *kva, void *ctxt, void *pres)
+{
+ deflim_t *pdef = pres;
+ char *val;
+
+ if (pdef->def == NULL) {
+ val = kva_match(kva, USERATTR_DFLTPRIV_KW);
+ if (val != NULL)
+ pdef->def = strdup(val);
+ }
+ if (pdef->lim == NULL) {
+ val = kva_match(kva, USERATTR_LIMPRIV_KW);
+ if (val != NULL)
+ pdef->lim = strdup(val);
+ }
+ return (pdef->lim != NULL && pdef->def != NULL);
+}
+
/*
* unix_cred - pam_sm_setcred
*
@@ -162,7 +183,6 @@ pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
au_id_t auid;
adt_session_data_t *ah;
adt_termid_t *termid = NULL;
- userattr_t *ua;
priv_set_t *lim, *def, *tset;
char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
char buf[PROJECT_BUFSZ];
@@ -172,7 +192,7 @@ pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
char *kvs;
struct passwd pwd;
char pwbuf[NSS_BUFLEN_PASSWD];
- void *defp;
+ deflim_t deflim;
for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "debug") == 0)
@@ -555,20 +575,23 @@ adt_done:
return (PAM_SYSTEM_ERR);
}
- ua = getusernam(user);
-
- defp = defopen_r(AUTH_POLICY);
-
tset = def = lim = NULL;
+ deflim.def = deflim.lim = NULL;
- if (getset(USERATTR_LIMPRIV_KW, DEF_LIMITPRIV, ua, &lim, defp) != 0 ||
- getset(USERATTR_DFLTPRIV_KW, DEF_DFLTPRIV, ua, &def, defp) != 0) {
+ (void) _enum_attrs(user, finddeflim, NULL, &deflim);
+
+ if (getset(deflim.lim, &lim) != 0 || getset(deflim.def, &def) != 0) {
ret = PAM_SYSTEM_ERR;
goto out;
}
if (def == NULL) {
- def = priv_str_to_set("basic", ",", NULL);
+ def = priv_allocset();
+ if (def == NULL) {
+ ret = PAM_SYSTEM_ERR;
+ goto out;
+ }
+ priv_basicset(def);
errno = 0;
if ((pathconf("/", _PC_CHOWN_RESTRICTED) == -1) && (errno == 0))
(void) priv_addset(def, PRIV_FILE_CHOWN_SELF);
@@ -627,13 +650,16 @@ adt_done:
* when the uids are set to their final values.
*/
(void) setpflags(PRIV_AWARE, 0);
+ /*
+ * Remove PRIV_PFEXEC; stop running as if we are under a profile
+ * shell. A user with a profile shell will set PRIV_PFEXEC.
+ */
+ (void) setpflags(PRIV_PFEXEC, 0);
out:
- if (defp != NULL)
- defclose_r(defp);
+ free(deflim.lim);
+ free(deflim.def);
- if (ua != NULL)
- free_userattr(ua);
if (lim != NULL)
priv_freeset(lim);
if (def != NULL)
diff --git a/usr/src/pkg/manifests/SUNWcs.mf b/usr/src/pkg/manifests/SUNWcs.mf
index f20c6e940e..2261c44e44 100644
--- a/usr/src/pkg/manifests/SUNWcs.mf
+++ b/usr/src/pkg/manifests/SUNWcs.mf
@@ -735,7 +735,7 @@ file path=usr/bin/pagesize mode=0555
file path=usr/bin/passwd group=sys mode=6555
file path=usr/bin/pathchk mode=0555
file path=usr/bin/pax mode=0555
-file path=usr/bin/pfexec mode=4555
+file path=usr/bin/pfexec mode=0555
file path=usr/bin/pg mode=0555
file path=usr/bin/pgrep mode=0555
file path=usr/bin/pkg2du mode=0555
@@ -1090,6 +1090,7 @@ file path=usr/lib/help/profiles/locale/C/RtPriAdmin.html
file path=usr/lib/help/profiles/locale/C/RtPrntAdmin.html
file path=usr/lib/help/profiles/locale/C/RtProcManagement.html
file path=usr/lib/help/profiles/locale/C/RtReparseMngmnt.html
+file path=usr/lib/help/profiles/locale/C/RtReservedProfile.html
file path=usr/lib/help/profiles/locale/C/RtRightsDelegate.html
file path=usr/lib/help/profiles/locale/C/RtSMBFSMngmnt.html
file path=usr/lib/help/profiles/locale/C/RtSMBMngmnt.html
@@ -1144,6 +1145,7 @@ file path=usr/lib/more.help
file path=usr/lib/newsyslog group=sys mode=0555
file path=usr/lib/pci/pcidr mode=0555
file path=usr/lib/pci/pcidr_plugin.so
+file path=usr/lib/pfexecd mode=0555
file path=usr/lib/platexec mode=0555
file path=usr/lib/rcm/modules/SUNW_aggr_rcm.so mode=0555
file path=usr/lib/rcm/modules/SUNW_cluster_rcm.so mode=0555
@@ -1963,6 +1965,7 @@ file path=lib/svc/manifest/system/keymap.xml group=sys mode=0444
file path=lib/svc/manifest/system/early-manifest-import.xml group=sys mode=0444
file path=lib/svc/manifest/system/manifest-import.xml group=sys mode=0444
file path=lib/svc/manifest/system/name-service-cache.xml group=sys mode=0444
+file path=lib/svc/manifest/system/pfexecd.xml group=sys mode=0444
file path=lib/svc/manifest/system/rbac.xml group=sys mode=0444
file path=lib/svc/manifest/system/rmtmpfiles.xml group=sys mode=0444
file path=lib/svc/manifest/system/sac.xml group=sys mode=0444
@@ -2006,20 +2009,12 @@ hardlink path=sbin/rc6 target=../sbin/rc0
hardlink path=usr/bin/$(ARCH32)/encrypt target=decrypt
hardlink path=usr/bin/$(ARCH32)/ksh target=ksh93
hardlink path=usr/bin/$(ARCH32)/mac target=digest
-hardlink path=usr/bin/$(ARCH32)/pfksh target=ksh93
-hardlink path=usr/bin/$(ARCH32)/pfksh93 target=ksh93
-hardlink path=usr/bin/$(ARCH32)/pfrksh target=ksh93
-hardlink path=usr/bin/$(ARCH32)/pfrksh93 target=ksh93
hardlink path=usr/bin/$(ARCH32)/rksh target=ksh93
hardlink path=usr/bin/$(ARCH32)/rksh93 target=ksh93
$(i386_ONLY)hardlink path=usr/bin/$(ARCH32)/w target=uptime
hardlink path=usr/bin/$(ARCH64)/encrypt target=decrypt
hardlink path=usr/bin/$(ARCH64)/ksh target=ksh93
hardlink path=usr/bin/$(ARCH64)/mac target=digest
-hardlink path=usr/bin/$(ARCH64)/pfksh target=ksh93
-hardlink path=usr/bin/$(ARCH64)/pfksh93 target=ksh93
-hardlink path=usr/bin/$(ARCH64)/pfrksh target=ksh93
-hardlink path=usr/bin/$(ARCH64)/pfrksh93 target=ksh93
hardlink path=usr/bin/$(ARCH64)/rksh target=ksh93
hardlink path=usr/bin/$(ARCH64)/rksh93 target=ksh93
hardlink path=usr/bin/$(ARCH64)/w target=uptime
@@ -2065,11 +2060,15 @@ hardlink path=usr/bin/nohup target=../../usr/lib/isaexec
hardlink path=usr/bin/page target=../../usr/bin/more
hardlink path=usr/bin/paste target=../../usr/bin/alias
hardlink path=usr/bin/pdp11 target=../../usr/bin/i286
-hardlink path=usr/bin/pfcsh target=../../usr/bin/csh
-hardlink path=usr/bin/pfksh target=../../usr/lib/isaexec
-hardlink path=usr/bin/pfksh93 target=../../usr/lib/isaexec
-hardlink path=usr/bin/pfrksh target=../../usr/lib/isaexec
-hardlink path=usr/bin/pfrksh93 target=../../usr/lib/isaexec
+hardlink path=usr/bin/pfbash target=../../usr/bin/pfexec
+hardlink path=usr/bin/pfcsh target=../../usr/bin/pfexec
+hardlink path=usr/bin/pfksh target=../../usr/bin/pfexec
+hardlink path=usr/bin/pfksh93 target=../../usr/bin/pfexec
+hardlink path=usr/bin/pfrksh target=../../usr/bin/pfexec
+hardlink path=usr/bin/pfrksh93 target=../../usr/bin/pfexec
+hardlink path=usr/bin/pfsh target=../../usr/bin/pfexec
+hardlink path=usr/bin/pftcsh target=../../usr/bin/pfexec
+hardlink path=usr/bin/pfzsh target=../../usr/bin/pfexec
hardlink path=usr/bin/pkill target=../../usr/bin/pgrep
hardlink path=usr/bin/prctl target=../../usr/lib/isaexec
hardlink path=usr/bin/print target=../../usr/bin/alias
@@ -2114,6 +2113,7 @@ hardlink path=usr/bin/w target=../../usr/lib/isaexec
hardlink path=usr/bin/wait target=../../usr/bin/alias
hardlink path=usr/bin/wc target=../../usr/bin/alias
hardlink path=usr/has/bin/ex target=edit
+hardlink path=usr/has/bin/pfsh target=../../bin/pfexec
hardlink path=usr/has/bin/vedit target=edit
hardlink path=usr/has/bin/vi target=edit
hardlink path=usr/has/bin/view target=edit
@@ -2501,6 +2501,7 @@ hardlink path=usr/share/lib/zoneinfo/W-SU \
target=../../../../usr/share/lib/zoneinfo/Europe/Moscow
hardlink path=usr/share/lib/zoneinfo/Zulu \
target=../../../../usr/share/lib/zoneinfo/Etc/UTC
+hardlink path=usr/xpg4/bin/pfsh target=../../bin/pfexec
$(sparc_ONLY)hardlink path=etc/svc/profile/platform_SUNW,Sun-Fire-V890.xml \
target=./platform_SUNW,Sun-Fire-880.xml
$(sparc_ONLY)hardlink \
@@ -2616,7 +2617,7 @@ link path=etc/whodo target=../usr/sbin/whodo
link path=etc/wtmpx target=../var/adm/wtmpx
link path=sbin/in.mpathd target=../lib/inet/in.mpathd
link path=sbin/jsh target=../usr/bin/ksh93
-link path=sbin/pfsh target=../usr/bin/ksh93
+link path=sbin/pfsh target=../usr/bin/pfexec
link path=sbin/sh target=../usr/bin/$(ARCH32)/ksh93
link path=sbin/su target=../usr/bin/su
link path=usr/adm target=../var/adm
@@ -2625,7 +2626,6 @@ link path=usr/bin/cachefsstat target=../lib/fs/cachefs/cachefsstat
link path=usr/bin/df target=../sbin/df
link path=usr/bin/jsh target=ksh93
link path=usr/bin/passmgmt target=../sbin/passmgmt
-link path=usr/bin/pfsh target=ksh93
link path=usr/bin/pwconv target=../sbin/pwconv
link path=usr/bin/rmail target=./mail
link path=usr/bin/sh target=$(ARCH32)/ksh93
@@ -2636,7 +2636,6 @@ link path=usr/bin/tar target=../sbin/tar
link path=usr/bin/uname target=../../sbin/uname
link path=usr/ccs/bin/m4 target=../../bin/m4
link path=usr/has/bin/jsh target=sh
-link path=usr/has/bin/pfsh target=sh
link path=usr/has/lib/rsh target=../bin/sh
link path=usr/lib/$(ARCH64)/ld.so.1 target=../../../lib/$(ARCH64)/ld.so.1
link path=usr/lib/cron target=../../etc/cron.d
diff --git a/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf b/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
index b74a9f2125..88db18dd8b 100644
--- a/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
+++ b/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
@@ -269,6 +269,7 @@ file path=usr/lib/help/profiles/locale/RtPriAdmin.html
file path=usr/lib/help/profiles/locale/RtPrntAdmin.html
file path=usr/lib/help/profiles/locale/RtProcManagement.html
file path=usr/lib/help/profiles/locale/RtReparseMngmnt.html
+file path=usr/lib/help/profiles/locale/RtReservedProfile.html
file path=usr/lib/help/profiles/locale/RtRightsDelegate.html
file path=usr/lib/help/profiles/locale/RtSMBFSMngmnt.html
file path=usr/lib/help/profiles/locale/RtSMBMngmnt.html
diff --git a/usr/src/pkg/manifests/shell-ksh88.mf b/usr/src/pkg/manifests/shell-ksh88.mf
index ef7b21aa75..525dc19cf9 100644
--- a/usr/src/pkg/manifests/shell-ksh88.mf
+++ b/usr/src/pkg/manifests/shell-ksh88.mf
@@ -1,5 +1,4 @@
-#
-# CDDL HEADER START
+# # CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
@@ -20,8 +19,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
set name=pkg.fmri value=pkg:/shell/ksh88@$(PKGVERS)
@@ -35,5 +33,5 @@ dir path=usr group=sys
dir path=usr/has
dir path=usr/has/bin
file path=usr/has/bin/ksh mode=0555
-hardlink path=usr/has/bin/pfksh target=ksh
+hardlink path=usr/has/bin/pfksh target=../../bin/pfexec
hardlink path=usr/has/bin/rksh target=ksh
diff --git a/usr/src/uts/common/c2/audit.c b/usr/src/uts/common/c2/audit.c
index 3641e2b212..0e99e777a7 100644
--- a/usr/src/uts/common/c2/audit.c
+++ b/usr/src/uts/common/c2/audit.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -60,7 +59,7 @@
#include <sys/disp.h> /* for servicing_interrupt() */
#include <sys/devpolicy.h>
#include <sys/crypto/ioctladmin.h>
-#include <sys/cred.h>
+#include <sys/cred_impl.h>
#include <inet/kssl/kssl.h>
#include <net/pfpolicy.h>
@@ -1232,13 +1231,13 @@ audit_vncreate_finish(struct vnode *vp, int error)
* QUESTION:
*/
-/*ARGSUSED*/
void
audit_exec(
const char *argstr, /* argument strings */
const char *envstr, /* environment strings */
ssize_t argc, /* total # arguments */
- ssize_t envc) /* total # environment variables */
+ ssize_t envc, /* total # environment variables */
+ cred_t *pfcred) /* the additional privileges in a profile */
{
t_audit_data_t *tad;
au_kcontext_t *kctx = GET_KCTX_PZ;
@@ -1249,17 +1248,52 @@ audit_exec(
if (!tad->tad_flag)
return;
- /* return if not interested in argv or environment variables */
- if (!(kctx->auk_policy & (AUDIT_ARGV|AUDIT_ARGE)))
- return;
+ if (pfcred != NULL) {
+ p_audit_data_t *pad;
+ cred_t *cr = CRED();
+ priv_set_t pset = CR_IPRIV(cr);
- if (kctx->auk_policy & AUDIT_ARGV) {
- au_uwrite(au_to_exec_args(argstr, argc));
+ pad = P2A(curproc);
+
+ /* It's a different event. */
+ tad->tad_event = AUE_PFEXEC;
+
+ /* Add the current working directory to the audit trail. */
+ if (pad->pad_cwd != NULL)
+ au_uwrite(au_to_path(pad->pad_cwd));
+
+ /*
+ * The new credential is not yet in place when audit_exec
+ * is called.
+ * Compute the additional bits available in the new credential
+ * and the limit set.
+ */
+ priv_inverse(&pset);
+ priv_intersect(&CR_IPRIV(pfcred), &pset);
+ if (!priv_isemptyset(&pset) ||
+ !priv_isequalset(&CR_LPRIV(pfcred), &CR_LPRIV(cr))) {
+ au_uwrite(au_to_privset(
+ priv_getsetbynum(PRIV_INHERITABLE), &pset, AUT_PRIV,
+ 0));
+ au_uwrite(au_to_privset(priv_getsetbynum(PRIV_LIMIT),
+ &CR_LPRIV(pfcred), AUT_PRIV, 0));
+ }
+ /*
+ * Compare the uids & gids: create a process token if changed.
+ */
+ if (crgetuid(cr) != crgetuid(pfcred) ||
+ crgetruid(cr) != crgetruid(pfcred) ||
+ crgetgid(cr) != crgetgid(pfcred) ||
+ crgetrgid(cr) != crgetrgid(pfcred)) {
+ AUDIT_SETPROC(&(u_ad), cr, crgetauinfo(cr));
+ }
}
- if (kctx->auk_policy & AUDIT_ARGE) {
+ if (pfcred != NULL || (kctx->auk_policy & AUDIT_ARGV) != 0)
+ au_uwrite(au_to_exec_args(argstr, argc));
+
+ if (kctx->auk_policy & AUDIT_ARGE)
au_uwrite(au_to_exec_env(envstr, envc));
- }
}
/*
diff --git a/usr/src/uts/common/c2/audit.h b/usr/src/uts/common/c2/audit.h
index 6be3d04f94..3b5e43cc50 100644
--- a/usr/src/uts/common/c2/audit.h
+++ b/usr/src/uts/common/c2/audit.h
@@ -529,7 +529,7 @@ void audit_reboot(void);
void audit_vncreate_start(void);
void audit_setfsat_path(int argnum);
void audit_vncreate_finish(struct vnode *, int);
-void audit_exec(const char *, const char *, ssize_t, ssize_t);
+void audit_exec(const char *, const char *, ssize_t, ssize_t, cred_t *);
void audit_enterprom(int);
void audit_exitprom(int);
void audit_chdirec(struct vnode *, struct vnode **);
diff --git a/usr/src/uts/common/c2/audit_kernel.h b/usr/src/uts/common/c2/audit_kernel.h
index d2c61c3257..956c30992a 100644
--- a/usr/src/uts/common/c2/audit_kernel.h
+++ b/usr/src/uts/common/c2/audit_kernel.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _BSM_AUDIT_KERNEL_H
@@ -409,6 +408,15 @@ au_buff_t *au_get_buff(void), *au_free_buff(au_buff_t *);
#define AUDIT_SETSUBJ(u, c, a, k) \
AUDIT_SETSUBJ_GENERIC(u, c, a, k, curproc->p_pid)
+#define AUDIT_SETPROC_GENERIC(u, c, a, p) \
+ (au_write((u), au_to_process(crgetuid(c), \
+ crgetgid(c), crgetruid(c), crgetrgid(c), \
+ p, (a)->ai_auid, (a)->ai_asid, \
+ &((a)->ai_termid))));
+
+#define AUDIT_SETPROC(u, c, a) \
+ AUDIT_SETPROC_GENERIC(u, c, a, curproc->p_pid)
+
/*
* Macros for type conversion
*/
diff --git a/usr/src/uts/common/c2/audit_kevents.h b/usr/src/uts/common/c2/audit_kevents.h
index fdc3c4dc37..b106fdd3d6 100644
--- a/usr/src/uts/common/c2/audit_kevents.h
+++ b/usr/src/uts/common/c2/audit_kevents.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _BSM_AUDIT_KEVENTS_H
@@ -159,8 +158,9 @@ extern "C" {
#define AUE_SYSTEMBOOT 113 /* =na system booted */
#define AUE_ASYNC_DAEMON_EXIT 114 /* =no async_daemon(2) exited */
#define AUE_NFSSVC_EXIT 115 /* =no nfssvc(2) exited */
+#define AUE_PFEXEC 116 /* =ps,ex,ua,as execve(2) w/ pfexec */
/*
- * 116 - 129 are available for future growth (old SunOS_CMW events
+ * 117 - 129 are available for future growth (old SunOS_CMW events
* that had no libbsm or praudit support or references)
*/
#define AUE_GETAUID 130 /* =aa getauid(2) */
diff --git a/usr/src/uts/common/c2/audit_start.c b/usr/src/uts/common/c2/audit_start.c
index 87f898f52f..6911b21094 100644
--- a/usr/src/uts/common/c2/audit_start.c
+++ b/usr/src/uts/common/c2/audit_start.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -465,6 +464,11 @@ auditme(au_kcontext_t *kctx, struct t_audit_data *tad, au_state_t estate)
kctx->auk_ets[AUE_SOCKRECEIVE];
if (amask.as_success & estate || amask.as_failure & estate)
flag = 1;
+ } else if (tad->tad_scid == SYS_execve &&
+ getpflags(PRIV_PFEXEC, CRED()) != 0) {
+ estate = kctx->auk_ets[AUE_PFEXEC];
+ if (amask.as_success & estate || amask.as_failure & estate)
+ flag = 1;
}
return (flag);
diff --git a/usr/src/uts/common/fs/autofs/auto_vfsops.c b/usr/src/uts/common/fs/autofs/auto_vfsops.c
index 388b7d9c29..3bd5fa7591 100644
--- a/usr/src/uts/common/fs/autofs/auto_vfsops.c
+++ b/usr/src/uts/common/fs/autofs/auto_vfsops.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/param.h>
@@ -193,6 +192,9 @@ autofs_zone_destructor(zoneid_t zoneid, void *arg)
return;
ASSERT(fngp->fng_fnnode_count == 1);
ASSERT(fngp->fng_unmount_threads == 0);
+
+ if (fngp->fng_autofs_daemon_dh != NULL)
+ door_ki_rele(fngp->fng_autofs_daemon_dh);
/*
* vn_alloc() initialized the rootnode with a count of 1; we need to
* make this 0 to placate auto_freefnnode().
diff --git a/usr/src/uts/common/fs/autofs/auto_vnops.c b/usr/src/uts/common/fs/autofs/auto_vnops.c
index 344aae643b..ebe3ce4055 100644
--- a/usr/src/uts/common/fs/autofs/auto_vnops.c
+++ b/usr/src/uts/common/fs/autofs/auto_vnops.c
@@ -337,10 +337,8 @@ auto_access(
if (groupmember(fnp->fn_gid, cred) == 0)
shift += 3;
}
- mode &= ~(fnp->fn_mode << shift);
- if (mode != 0)
- error = secpolicy_vnode_access(cred, vp, fnp->fn_uid,
- mode);
+ error = secpolicy_vnode_access2(cred, vp, fnp->fn_uid,
+ fnp->fn_mode << shift, mode);
}
done:
diff --git a/usr/src/uts/common/fs/cachefs/cachefs_vnops.c b/usr/src/uts/common/fs/cachefs/cachefs_vnops.c
index 5f5005d565..625a5ec553 100644
--- a/usr/src/uts/common/fs/cachefs/cachefs_vnops.c
+++ b/usr/src/uts/common/fs/cachefs/cachefs_vnops.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/param.h>
@@ -402,8 +401,8 @@ cachefs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
* cnode disallow writing while disconnected.
*/
if (crcmp(cp->c_cred, CRED()) != 0 &&
- secpolicy_vnode_access(CRED(), *vpp,
- cp->c_attr.va_uid, VWRITE) != 0) {
+ secpolicy_vnode_access2(CRED(), *vpp,
+ cp->c_attr.va_uid, 0, VWRITE) != 0) {
mutex_exit(&cp->c_statelock);
connected = 1;
continue;
@@ -9829,13 +9828,8 @@ cachefs_access_local(void *vcp, int mode, cred_t *cr)
shift += 3;
}
- /* compute missing mode bits */
- mode &= ~(cp->c_attr.va_mode << shift);
-
- if (mode == 0)
- return (0);
-
- return (secpolicy_vnode_access(cr, CTOV(cp), cp->c_attr.va_uid, mode));
+ return (secpolicy_vnode_access2(cr, CTOV(cp), cp->c_attr.va_uid,
+ cp->c_attr.va_mode << shift, mode));
}
/*
@@ -9849,8 +9843,8 @@ cachefs_access_local(void *vcp, int mode, cred_t *cr)
* Check Algorithm, of the POSIX 1003.6 Draft Standard.
*/
-#define ACL_MODE_CHECK(M, PERM, C, I) ((((M) & (PERM)) == (M)) ? 0 : \
- secpolicy_vnode_access(C, CTOV(I), owner, (M) & ~(PERM)))
+#define ACL_MODE_CHECK(M, PERM, C, I) \
+ secpolicy_vnode_access2(C, CTOV(I), owner, (PERM), (M))
static int
cachefs_acl_access(struct cnode *cp, int mode, cred_t *cr)
diff --git a/usr/src/uts/common/fs/dev/sdev_vnops.c b/usr/src/uts/common/fs/dev/sdev_vnops.c
index 6519dd32ca..416c100125 100644
--- a/usr/src/uts/common/fs/dev/sdev_vnops.c
+++ b/usr/src/uts/common/fs/dev/sdev_vnops.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -323,11 +322,8 @@ sdev_unlocked_access(void *vdv, int mode, struct cred *cr)
shift += 3;
}
- mode &= ~(dv->sdev_attr->va_mode << shift);
- if (mode == 0)
- return (0);
-
- return (secpolicy_vnode_access(cr, SDEVTOV(dv), owner, mode));
+ return (secpolicy_vnode_access2(cr, SDEVTOV(dv), owner,
+ dv->sdev_attr->va_mode << shift, mode));
}
static int
diff --git a/usr/src/uts/common/fs/devfs/devfs_vnops.c b/usr/src/uts/common/fs/devfs/devfs_vnops.c
index 359e9e1d6a..0c5114066b 100644
--- a/usr/src/uts/common/fs/devfs/devfs_vnops.c
+++ b/usr/src/uts/common/fs/devfs/devfs_vnops.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -719,13 +718,8 @@ devfs_unlocked_access(void *vdv, int mode, struct cred *cr)
shift += 3;
}
- /* compute missing mode bits */
- mode &= ~(dv->dv_attr->va_mode << shift);
-
- if (mode == 0)
- return (0);
-
- return (secpolicy_vnode_access(cr, DVTOV(dv), owner, mode));
+ return (secpolicy_vnode_access2(cr, DVTOV(dv), owner,
+ dv->dv_attr->va_mode << shift, mode));
}
static int
diff --git a/usr/src/uts/common/fs/hsfs/hsfs_node.c b/usr/src/uts/common/fs/hsfs/hsfs_node.c
index 58dbe56e1a..6e9456f65f 100644
--- a/usr/src/uts/common/fs/hsfs/hsfs_node.c
+++ b/usr/src/uts/common/fs/hsfs/hsfs_node.c
@@ -19,12 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Directory operations for High Sierra filesystem
*/
@@ -157,10 +154,8 @@ hs_access(struct vnode *vp, mode_t m, struct cred *cred)
if (!groupmember((uid_t)hp->hs_dirent.gid, cred))
shift += 3;
}
- m &= ~(hp->hs_dirent.mode << shift);
- if (m != 0)
- return (secpolicy_vnode_access(cred, vp, hp->hs_dirent.uid, m));
- return (0);
+ return (secpolicy_vnode_access2(cred, vp, hp->hs_dirent.uid,
+ hp->hs_dirent.mode << shift, m));
}
#if ((HS_HASHSIZE & (HS_HASHSIZE - 1)) == 0)
diff --git a/usr/src/uts/common/fs/namefs/namevfs.c b/usr/src/uts/common/fs/namefs/namevfs.c
index a6670d9cd6..b0470e45d9 100644
--- a/usr/src/uts/common/fs/namefs/namevfs.c
+++ b/usr/src/uts/common/fs/namefs/namevfs.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -417,8 +416,8 @@ nm_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *crp)
* Make sure the user has write permissions on the
* mount point (or has sufficient privileges).
*/
- if (!(vattrp->va_mode & VWRITE) &&
- secpolicy_vnode_access(crp, mvp, vattrp->va_uid, VWRITE) != 0) {
+ if (secpolicy_vnode_access2(crp, mvp, vattrp->va_uid, vattrp->va_mode,
+ VWRITE) != 0) {
error = EACCES;
goto out;
}
diff --git a/usr/src/uts/common/fs/namefs/namevno.c b/usr/src/uts/common/fs/namefs/namevno.c
index f487953db5..e1f8590718 100644
--- a/usr/src/uts/common/fs/namefs/namevno.c
+++ b/usr/src/uts/common/fs/namefs/namevno.c
@@ -23,12 +23,9 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* This file defines the vnode operations for mounted file descriptors.
* The routines in this file act as a layer between the NAMEFS file
@@ -253,13 +250,10 @@ nm_access_unlocked(void *vnp, int mode, cred_t *crp)
if (!groupmember(nodep->nm_vattr.va_gid, crp))
shift += 3;
}
- mode &= ~(nodep->nm_vattr.va_mode << shift);
-
- if (mode == 0)
- return (0);
- return (secpolicy_vnode_access(crp, NMTOV(nodep),
- nodep->nm_vattr.va_uid, mode));
+ return (secpolicy_vnode_access2(crp, NMTOV(nodep),
+ nodep->nm_vattr.va_uid, nodep->nm_vattr.va_mode << shift,
+ mode));
}
/*
* Set the attributes of the namenode from the attributes in vap.
diff --git a/usr/src/uts/common/fs/nfs/nfs_vnops.c b/usr/src/uts/common/fs/nfs/nfs_vnops.c
index fa7ba8b791..a3f43a4e95 100644
--- a/usr/src/uts/common/fs/nfs/nfs_vnops.c
+++ b/usr/src/uts/common/fs/nfs/nfs_vnops.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
* All rights reserved.
@@ -1445,12 +1444,9 @@ nfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
if (!groupmember(va.va_gid, cr))
shift += 3;
}
-found:
- mode &= ~(va.va_mode << shift);
- if (mode == 0)
- return (0);
- return (secpolicy_vnode_access(cr, vp, va.va_uid, mode));
+ return (secpolicy_vnode_access2(cr, vp, va.va_uid,
+ va.va_mode << shift, mode));
}
static int nfs_do_symlink_cache = 1;
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
index 30926e61b0..048c159fdf 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
@@ -33,8 +33,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/systm.h>
@@ -1211,9 +1210,6 @@ smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
if (!groupmember(va.va_gid, cr))
shift += 3;
}
- mode &= ~(va.va_mode << shift);
- if (mode == 0)
- return (0);
/*
* We need a vnode for secpolicy_vnode_access,
@@ -1223,7 +1219,9 @@ smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
tvp = (va.va_type == VDIR) ?
(vnode_t *)&tmpl_vdir :
(vnode_t *)&tmpl_vreg;
- return (secpolicy_vnode_access(cr, tvp, va.va_uid, mode));
+
+ return (secpolicy_vnode_access2(cr, tvp, va.va_uid,
+ va.va_mode << shift, mode));
}
/*
diff --git a/usr/src/uts/common/fs/tmpfs/tmp_subr.c b/usr/src/uts/common/fs/tmpfs/tmp_subr.c
index 0012dfe35a..2e59d28d80 100644
--- a/usr/src/uts/common/fs/tmpfs/tmp_subr.c
+++ b/usr/src/uts/common/fs/tmpfs/tmp_subr.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 1989-1999,2001-2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/param.h>
@@ -62,13 +58,8 @@ tmp_taccess(void *vtp, int mode, struct cred *cred)
shift += MODESHIFT;
}
- /* compute missing mode bits */
- mode &= ~(tp->tn_mode << shift);
-
- if (mode == 0)
- return (0);
-
- return (secpolicy_vnode_access(cred, TNTOV(tp), tp->tn_uid, mode));
+ return (secpolicy_vnode_access2(cred, TNTOV(tp), tp->tn_uid,
+ tp->tn_mode << shift, mode));
}
/*
diff --git a/usr/src/uts/common/fs/udfs/udf_inode.c b/usr/src/uts/common/fs/udfs/udf_inode.c
index 72440ffcc2..e30a5ffe6d 100644
--- a/usr/src/uts/common/fs/udfs/udf_inode.c
+++ b/usr/src/uts/common/fs/udfs/udf_inode.c
@@ -1963,13 +1963,9 @@ ud_iaccess(struct ud_inode *ip, int32_t mode, struct cred *cr, int dolock)
if (!groupmember((uid_t)ip->i_gid, cr))
shift += 5;
}
- mode &= ~(ip->i_perm << shift);
- if (mode == 0)
- goto out;
-
- ret = secpolicy_vnode_access(cr, ITOV(ip), ip->i_uid,
- UD2VA_PERM(mode));
+ ret = secpolicy_vnode_access2(cr, ITOV(ip), ip->i_uid,
+ UD2VA_PERM(ip->i_perm << shift), UD2VA_PERM(mode));
out:
if (dolock)
diff --git a/usr/src/uts/common/fs/ufs/ufs_inode.c b/usr/src/uts/common/fs/ufs/ufs_inode.c
index 40e051005a..ebb3fd6e9c 100644
--- a/usr/src/uts/common/fs/ufs/ufs_inode.c
+++ b/usr/src/uts/common/fs/ufs/ufs_inode.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -1566,13 +1565,9 @@ ufs_iaccess(struct inode *ip, int mode, struct cred *cr, int dolock)
shift += 3;
}
- mode &= ~(ip->i_mode << shift);
-
- if (mode == 0)
- goto out;
-
/* test missing privilege bits */
- ret = secpolicy_vnode_access(cr, ITOV(ip), ip->i_uid, mode);
+ ret = secpolicy_vnode_access2(cr, ITOV(ip), ip->i_uid,
+ ip->i_mode << shift, mode);
out:
if (dolock)
rw_exit(&ip->i_contents);
diff --git a/usr/src/uts/common/fs/zfs/zfs_acl.c b/usr/src/uts/common/fs/zfs/zfs_acl.c
index 34ace4a885..703f665964 100644
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_acl.c
@@ -2251,15 +2251,8 @@ zfs_has_access(znode_t *zp, cred_t *cr)
uint32_t have = ACE_ALL_PERMS;
if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr) != 0) {
- return (
- secpolicy_vnode_access(cr, ZTOV(zp),
- zp->z_uid, VREAD) == 0 || secpolicy_vnode_access(cr,
- ZTOV(zp), zp->z_uid, VWRITE) == 0 ||
- secpolicy_vnode_access(cr, ZTOV(zp),
- zp->z_uid, VEXEC) == 0 ||
- secpolicy_vnode_chown(cr, zp->z_uid) == 0 ||
- secpolicy_vnode_setdac(cr, zp->z_uid) == 0 ||
- secpolicy_vnode_remove(cr) == 0);
+ return (secpolicy_vnode_any_access(cr, ZTOV(zp),
+ zp->z_uid) == 0);
}
return (B_TRUE);
}
@@ -2379,8 +2372,9 @@ slow:
}
/*
- * Determine whether Access should be granted/denied, invoking least
- * priv subsytem when a deny is determined.
+ * Determine whether Access should be granted/denied.
+ * The least priv subsytem is always consulted as a basic privilege
+ * can define any form of access.
*/
int
zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
@@ -2391,6 +2385,7 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
boolean_t check_privs;
znode_t *xzp;
znode_t *check_zp = zp;
+ mode_t needed_bits;
is_attr = ((zp->z_pflags & ZFS_XATTR) && (ZTOV(zp)->v_type == VDIR));
@@ -2427,11 +2422,35 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
}
}
+ /*
+ * Map the bits required to the standard vnode flags VREAD|VWRITE|VEXEC
+ * in needed_bits. Map the bits mapped by working_mode (currently
+ * missing) in missing_bits.
+ * Call secpolicy_vnode_access2() with (needed_bits & ~checkmode),
+ * needed_bits.
+ */
+ needed_bits = 0;
+
+ working_mode = mode;
+ if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&
+ zp->z_uid == crgetuid(cr))
+ working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES);
+
+ if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS|
+ ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE))
+ needed_bits |= VREAD;
+ if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS|
+ ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE))
+ needed_bits |= VWRITE;
+ if (working_mode & ACE_EXECUTE)
+ needed_bits |= VEXEC;
+
if ((error = zfs_zaccess_common(check_zp, mode, &working_mode,
&check_privs, skipaclchk, cr)) == 0) {
if (is_attr)
VN_RELE(ZTOV(xzp));
- return (0);
+ return (secpolicy_vnode_access2(cr, ZTOV(zp), zp->z_uid,
+ needed_bits, needed_bits));
}
if (error && !check_privs) {
@@ -2468,9 +2487,8 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
if (working_mode & ACE_EXECUTE)
checkmode |= VEXEC;
- if (checkmode)
- error = secpolicy_vnode_access(cr, ZTOV(check_zp),
- zp->z_uid, checkmode);
+ error = secpolicy_vnode_access2(cr, ZTOV(check_zp), zp->z_uid,
+ needed_bits & ~checkmode, needed_bits);
if (error == 0 && (working_mode & ACE_WRITE_OWNER))
error = secpolicy_vnode_chown(cr, zp->z_uid);
@@ -2493,8 +2511,12 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
error = EACCES;
}
}
+ } else if (error == 0) {
+ error = secpolicy_vnode_access2(cr, ZTOV(zp), zp->z_uid,
+ needed_bits, needed_bits);
}
+
if (is_attr)
VN_RELE(ZTOV(xzp));
@@ -2524,12 +2546,12 @@ zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr)
static int
zfs_delete_final_check(znode_t *zp, znode_t *dzp,
- mode_t missing_perms, cred_t *cr)
+ mode_t available_perms, cred_t *cr)
{
int error;
- error = secpolicy_vnode_access(cr, ZTOV(dzp),
- dzp->z_uid, missing_perms);
+ error = secpolicy_vnode_access2(cr, ZTOV(dzp),
+ dzp->z_uid, available_perms, VWRITE|VEXEC);
if (error == 0)
error = zfs_sticky_remove_access(dzp, zp, cr);
@@ -2578,7 +2600,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
uint32_t dzp_working_mode = 0;
uint32_t zp_working_mode = 0;
int dzp_error, zp_error;
- mode_t missing_perms;
+ mode_t available_perms;
boolean_t dzpcheck_privs = B_TRUE;
boolean_t zpcheck_privs = B_TRUE;
@@ -2639,23 +2661,20 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
* only need to see if we have write/execute on directory.
*/
- if ((dzp_error = zfs_zaccess_common(dzp, ACE_EXECUTE|ACE_WRITE_DATA,
- &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr)) == 0)
- return (zfs_sticky_remove_access(dzp, zp, cr));
+ dzp_error = zfs_zaccess_common(dzp, ACE_EXECUTE|ACE_WRITE_DATA,
+ &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr);
- if (!dzpcheck_privs)
+ if (dzp_error != 0 && !dzpcheck_privs)
return (dzp_error);
/*
* Fourth row
*/
- missing_perms = (dzp_working_mode & ACE_WRITE_DATA) ? VWRITE : 0;
- missing_perms |= (dzp_working_mode & ACE_EXECUTE) ? VEXEC : 0;
-
- ASSERT(missing_perms);
+ available_perms = (dzp_working_mode & ACE_WRITE_DATA) ? 0 : VWRITE;
+ available_perms |= (dzp_working_mode & ACE_EXECUTE) ? 0 : VEXEC;
- return (zfs_delete_final_check(zp, dzp, missing_perms, cr));
+ return (zfs_delete_final_check(zp, dzp, available_perms, cr));
}
diff --git a/usr/src/uts/common/inet/ip/icmp.c b/usr/src/uts/common/inet/ip/icmp.c
index fa4c7a8b57..b024baaf0c 100644
--- a/usr/src/uts/common/inet/ip/icmp.c
+++ b/usr/src/uts/common/inet/ip/icmp.c
@@ -38,7 +38,7 @@
#include <sys/xti_inet.h>
#include <sys/cmn_err.h>
#include <sys/kmem.h>
-#include <sys/cred_impl.h>
+#include <sys/cred.h>
#include <sys/policy.h>
#include <sys/priv.h>
#include <sys/ucred.h>
diff --git a/usr/src/uts/common/inet/ip/spdsock.c b/usr/src/uts/common/inet/ip/spdsock.c
index 4a9053cddf..37dc31875e 100644
--- a/usr/src/uts/common/inet/ip/spdsock.c
+++ b/usr/src/uts/common/inet/ip/spdsock.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/param.h>
@@ -156,6 +155,7 @@ static void spdsock_wput(queue_t *, mblk_t *);
static void spdsock_wsrv(queue_t *);
static void spdsock_rsrv(queue_t *);
static void *spdsock_stack_init(netstackid_t stackid, netstack_t *ns);
+static void spdsock_stack_shutdown(netstackid_t stackid, void *arg);
static void spdsock_stack_fini(netstackid_t stackid, void *arg);
static void spdsock_loadcheck(void *);
static void spdsock_merge_algs(spd_stack_t *);
@@ -276,8 +276,8 @@ spdsock_ddi_init(void)
* destroyed in the kernel, so we can maintain the
* set of spd_stack_t's.
*/
- netstack_register(NS_SPDSOCK, spdsock_stack_init, NULL,
- spdsock_stack_fini);
+ netstack_register(NS_SPDSOCK, spdsock_stack_init,
+ spdsock_stack_shutdown, spdsock_stack_fini);
return (B_TRUE);
}
@@ -340,13 +340,28 @@ spdsock_ddi_destroy(void)
netstack_unregister(NS_SPDSOCK);
}
+/*
+ * Do pre-removal cleanup.
+ */
+/* ARGSUSED */
+static void
+spdsock_stack_shutdown(netstackid_t stackid, void *arg)
+{
+ spd_stack_t *spds = (spd_stack_t *)arg;
+
+ if (spds->spds_mp_algs != NULL) {
+ freemsg(spds->spds_mp_algs);
+ spds->spds_mp_algs = NULL;
+ }
+}
+
/* ARGSUSED */
static void
spdsock_stack_fini(netstackid_t stackid, void *arg)
{
spd_stack_t *spds = (spd_stack_t *)arg;
- freemsg(spds->spds_mp_algs);
+ ASSERT(spds->spds_mp_algs == NULL);
mutex_destroy(&spds->spds_param_lock);
mutex_destroy(&spds->spds_alg_lock);
nd_free(&spds->spds_g_nd);
@@ -2794,7 +2809,6 @@ spdsock_updatealg(queue_t *q, mblk_t *mp, spd_ext_t *extv[])
if (spds->spds_mp_algs != NULL)
freemsg(spds->spds_mp_algs);
spds->spds_mp_algs = mp;
- spds->spds_algs_pending = B_TRUE;
mutex_exit(&spds->spds_alg_lock);
if (auditing) {
cred_t *cr;
@@ -3152,9 +3166,10 @@ spdsock_update_pending_algs(netstack_t *ns)
spd_stack_t *spds = ns->netstack_spdsock;
mutex_enter(&spds->spds_alg_lock);
- if (spds->spds_algs_pending) {
+ if (spds->spds_mp_algs != NULL) {
(void) spdsock_do_updatealg(spds->spds_extv_algs, spds);
- spds->spds_algs_pending = B_FALSE;
+ freemsg(spds->spds_mp_algs);
+ spds->spds_mp_algs = NULL;
}
mutex_exit(&spds->spds_alg_lock);
}
diff --git a/usr/src/uts/common/inet/spdsock.h b/usr/src/uts/common/inet/spdsock.h
index 64c63cdd71..7cc065d740 100644
--- a/usr/src/uts/common/inet/spdsock.h
+++ b/usr/src/uts/common/inet/spdsock.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _INET_SPDSOCK_H
@@ -49,7 +48,6 @@ struct spd_stack {
*/
struct spd_ext *spds_extv_algs[SPD_EXT_MAX + 1];
mblk_t *spds_mp_algs;
- boolean_t spds_algs_pending;
struct ipsec_alginfo
*spds_algs[IPSEC_NALGTYPES][IPSEC_MAX_ALGS];
int spds_algs_exec_mode[IPSEC_NALGTYPES];
diff --git a/usr/src/uts/common/os/cred.c b/usr/src/uts/common/os/cred.c
index 01dc69774d..93a274f2d1 100644
--- a/usr/src/uts/common/os/cred.c
+++ b/usr/src/uts/common/os/cred.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -348,6 +347,7 @@ crset(proc_t *p, cred_t *cr)
void
crhold(cred_t *cr)
{
+ ASSERT(cr->cr_ref != 0xdeadbeef && cr->cr_ref != 0);
atomic_add_32(&cr->cr_ref, 1);
}
@@ -358,6 +358,7 @@ crhold(cred_t *cr)
void
crfree(cred_t *cr)
{
+ ASSERT(cr->cr_ref != 0xdeadbeef && cr->cr_ref != 0);
if (atomic_add_32_nv(&cr->cr_ref, -1) == 0) {
ASSERT(cr != kcred);
if (cr->cr_label)
@@ -901,7 +902,7 @@ cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo, const cred_t *rcr)
auditinfo_addr_t *ai;
au_tid_addr_t tid;
- if (secpolicy_audit_getattr(rcr) != 0)
+ if (secpolicy_audit_getattr(rcr, B_TRUE) != 0)
return (-1);
ai = CR_AUINFO(cr); /* caller makes sure this is non-NULL */
diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c
index f9cf4e1eea..c01c81062c 100644
--- a/usr/src/uts/common/os/exec.c
+++ b/usr/src/uts/common/os/exec.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1988 AT&T */
@@ -66,6 +65,7 @@
#include <sys/pool.h>
#include <sys/sdt.h>
#include <sys/brand.h>
+#include <sys/klpd.h>
#include <c2/audit.h>
@@ -80,8 +80,10 @@
#define PRIV_SETUGID 0x04 /* is setuid/setgid/forced privs */
#define PRIV_INCREASE 0x08 /* child runs with more privs */
#define MAC_FLAGS 0x10 /* need to adjust MAC flags */
+#define PRIV_FORCED 0x20 /* has forced privileges */
-static int execsetid(struct vnode *, struct vattr *, uid_t *, uid_t *);
+static int execsetid(struct vnode *, struct vattr *, uid_t *, uid_t *,
+ priv_set_t *, cred_t *, const char *);
static int hold_execsw(struct execsw *);
uint_t auxv_hwcap = 0; /* auxv AT_SUN_HWCAP value; determined on the fly */
@@ -252,6 +254,31 @@ exec_common(const char *fname, const char **argp, const char **envp,
pn_free(&pn);
/*
+ * If we're running in a profile shell, then call pfexecd.
+ */
+ if ((CR_FLAGS(p->p_cred) & PRIV_PFEXEC) != 0) {
+ error = pfexec_call(p->p_cred, &resolvepn, &args.pfcred,
+ &args.scrubenv);
+
+ /* Returning errno in case we're not allowed to execute. */
+ if (error > 0) {
+ if (dir != NULL)
+ VN_RELE(dir);
+ pn_free(&resolvepn);
+ VN_RELE(vp);
+ goto out;
+ }
+
+ /* Don't change the credentials when using old ptrace. */
+ if (args.pfcred != NULL &&
+ (p->p_proc_flag & P_PR_PTRACE) != 0) {
+ crfree(args.pfcred);
+ args.pfcred = NULL;
+ args.scrubenv = B_FALSE;
+ }
+ }
+
+ /*
* Specific exec handlers, or policies determined via
* /etc/system may override the historical default.
*/
@@ -527,6 +554,7 @@ gexec(
cred_t *oldcred, *newcred = NULL;
int privflags = 0;
int setidfl;
+ priv_set_t fset;
/*
* If the SNOCD or SUGID flag is set, turn it off and remember the
@@ -562,9 +590,17 @@ gexec(
goto bad;
if (level == 0 &&
- (privflags = execsetid(vp, &vattr, &uid, &gid)) != 0) {
+ (privflags = execsetid(vp, &vattr, &uid, &gid, &fset,
+ args->pfcred == NULL ? cred : args->pfcred, args->pathname)) != 0) {
+
+ /* Pfcred is a credential with a ref count of 1 */
- newcred = cred = crdup(cred);
+ if (args->pfcred != NULL) {
+ privflags |= PRIV_INCREASE|PRIV_RESET;
+ newcred = cred = args->pfcred;
+ } else {
+ newcred = cred = crdup(cred);
+ }
/* If we can, drop the PA bit */
if ((privflags & PRIV_RESET) != 0)
@@ -592,17 +628,31 @@ gexec(
*
* E' = P' = (I' + F) & A
*
- * But if running under ptrace, we cap I with P.
+ * But if running under ptrace, we cap I and F with P.
*/
- if ((privflags & PRIV_RESET) != 0) {
+ if ((privflags & (PRIV_RESET|PRIV_FORCED)) != 0) {
if ((privflags & PRIV_INCREASE) != 0 &&
- (pp->p_proc_flag & P_PR_PTRACE) != 0)
+ (pp->p_proc_flag & P_PR_PTRACE) != 0) {
priv_intersect(&CR_OPPRIV(cred),
&CR_IPRIV(cred));
+ priv_intersect(&CR_OPPRIV(cred), &fset);
+ }
priv_intersect(&CR_LPRIV(cred), &CR_IPRIV(cred));
CR_EPRIV(cred) = CR_PPRIV(cred) = CR_IPRIV(cred);
+ if (privflags & PRIV_FORCED) {
+ priv_set_PA(cred);
+ priv_union(&fset, &CR_EPRIV(cred));
+ priv_union(&fset, &CR_PPRIV(cred));
+ }
priv_adjust_PA(cred);
}
+ } else if (level == 0 && args->pfcred != NULL) {
+ newcred = cred = args->pfcred;
+ privflags |= PRIV_INCREASE;
+ /* pfcred is not forced to adhere to these settings */
+ priv_intersect(&CR_LPRIV(cred), &CR_IPRIV(cred));
+ CR_EPRIV(cred) = CR_PPRIV(cred) = CR_IPRIV(cred);
+ priv_adjust_PA(cred);
}
/* SunOS 4.x buy-back */
@@ -659,7 +709,7 @@ gexec(
* credentials of the process. In privflags, it told us
* whether we gained any privileges or executed a set-uid executable.
*/
- setid = (privflags & (PRIV_SETUGID|PRIV_INCREASE));
+ setid = (privflags & (PRIV_SETUGID|PRIV_INCREASE|PRIV_FORCED));
/*
* Use /etc/system variable to determine if the stack
@@ -692,7 +742,7 @@ gexec(
}
if (setid & PRIV_SETUGID)
setidfl |= EXECSETID_SETID;
- if (setid & PRIV_INCREASE)
+ if (setid & PRIV_FORCED)
setidfl |= EXECSETID_PRIVS;
execvp = pp->p_exec;
@@ -718,6 +768,8 @@ gexec(
}
if (level == 0) {
+ uid_t oruid;
+
if (execvp != NULL) {
/*
* Close the previous executable only if we are
@@ -728,6 +780,9 @@ gexec(
}
mutex_enter(&pp->p_crlock);
+
+ oruid = pp->p_cred->cr_ruid;
+
if (newcred != NULL) {
/*
* Free the old credentials, and set the new ones.
@@ -778,6 +833,13 @@ gexec(
suidflags = 0;
mutex_exit(&pp->p_crlock);
+ if (newcred != NULL && oruid != newcred->cr_ruid) {
+ /* Note that the process remains in the same zone. */
+ mutex_enter(&pidlock);
+ upcount_dec(oruid, crgetzoneid(newcred));
+ upcount_inc(newcred->cr_ruid, crgetzoneid(newcred));
+ mutex_exit(&pidlock);
+ }
if (suidflags) {
mutex_enter(&pp->p_lock);
pp->p_flag |= suidflags;
@@ -929,11 +991,11 @@ hold_execsw(struct execsw *eswp)
}
static int
-execsetid(struct vnode *vp, struct vattr *vattrp, uid_t *uidp, uid_t *gidp)
+execsetid(struct vnode *vp, struct vattr *vattrp, uid_t *uidp, uid_t *gidp,
+ priv_set_t *fset, cred_t *cr, const char *pathname)
{
proc_t *pp = ttoproc(curthread);
uid_t uid, gid;
- cred_t *cr = pp->p_cred;
int privflags = 0;
/*
@@ -948,13 +1010,38 @@ execsetid(struct vnode *vp, struct vattr *vattrp, uid_t *uidp, uid_t *gidp)
if ((vp->v_vfsp->vfs_flag & VFS_NOSETUID) == 0) {
/*
- * Set-uid root execution only allowed if the limit set
- * holds all unsafe privileges.
+ * If it's a set-uid root program we perform the
+ * forced privilege look-aside. This has three possible
+ * outcomes:
+ * no look aside information -> treat as before
+ * look aside in Limit set -> apply forced privs
+ * look aside not in Limit set -> ignore set-uid root
+ *
+ * Ordinary set-uid root execution only allowed if the limit
+ * set holds all unsafe privileges.
*/
- if ((vattrp->va_mode & VSUID) && (vattrp->va_uid != 0 ||
- priv_issubset(&priv_unsafe, &CR_LPRIV(cr)))) {
- uid = vattrp->va_uid;
- privflags |= PRIV_SETUGID;
+ if (vattrp->va_mode & VSUID) {
+ if (vattrp->va_uid == 0) {
+ int res = get_forced_privs(cr, pathname, fset);
+
+ switch (res) {
+ case -1:
+ if (priv_issubset(&priv_unsafe,
+ &CR_LPRIV(cr))) {
+ uid = vattrp->va_uid;
+ privflags |= PRIV_SETUGID;
+ }
+ break;
+ case 0:
+ privflags |= PRIV_FORCED|PRIV_INCREASE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ uid = vattrp->va_uid;
+ privflags |= PRIV_SETUGID;
+ }
}
if (vattrp->va_mode & VSGID) {
gid = vattrp->va_gid;
@@ -980,20 +1067,14 @@ execsetid(struct vnode *vp, struct vattr *vattrp, uid_t *uidp, uid_t *gidp)
!priv_isequalset(&CR_PPRIV(cr), &CR_IPRIV(cr)))
privflags |= PRIV_RESET;
+ /* Child has more privileges than parent */
+ if (!priv_issubset(&CR_IPRIV(cr), &CR_PPRIV(cr)))
+ privflags |= PRIV_INCREASE;
+
/* If MAC-aware flag(s) are on, need to update cred to remove. */
if ((CR_FLAGS(cr) & NET_MAC_AWARE) ||
(CR_FLAGS(cr) & NET_MAC_AWARE_INHERIT))
privflags |= MAC_FLAGS;
-
- /*
- * When we introduce the "forced" set then we will need
- * to set PRIV_INCREASE here if I not a subset of P.
- * If the "allowed" set is introduced we will need to do
- * a similar thing; however, it seems more reasonable to
- * have the allowed set reduce "L": script language interpreters
- * would typically have an allowed set of "all".
- */
-
/*
* Set setuid/setgid protections if no ptrace() compatibility.
* For privileged processes, honor setuid/setgid even in
@@ -1498,12 +1579,18 @@ stk_copyin(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp)
*/
if (envp != NULL) {
for (;;) {
+ char *tmp = args->stk_strp;
if (stk_getptr(args, envp, &sp))
return (EFAULT);
if (sp == NULL)
break;
if ((error = stk_add(args, sp, UIO_USERSPACE)) != 0)
return (error);
+ if (args->scrubenv && strncmp(tmp, "LD_", 3) == 0) {
+ /* Undo the copied string */
+ args->stk_strp = tmp;
+ *(args->stk_offp++) = NULL;
+ }
envp += ptrsize;
}
}
@@ -1840,7 +1927,7 @@ exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp)
if (AU_AUDITING())
audit_exec(args->stk_base, args->stk_base + args->arglen,
- args->na - args->ne, args->ne);
+ args->na - args->ne, args->ne, args->pfcred);
/*
* Ensure that we don't change resource associations while we
diff --git a/usr/src/uts/common/os/klpd.c b/usr/src/uts/common/os/klpd.c
index 5441b20cef..2d7cd7e1c5 100644
--- a/usr/src/uts/common/os/klpd.c
+++ b/usr/src/uts/common/os/klpd.c
@@ -20,12 +20,9 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/atomic.h>
#include <sys/door.h>
#include <sys/proc.h>
@@ -139,21 +136,21 @@ klpd_unlink(klpd_reg_t *p)
}
/*
- * Remove the head of the klpd list and decrement its refcnt.
+ * Remove all elements of the klpd list and decrement their refcnts.
* The lock guarding the list should be held; this function is
- * called when we are sure we want to remove the entry from the
- * list but not so sure that the reference count has dropped back to
- * 1 and is specifically intended to remove the non-list variants.
+ * called when we are sure we want to destroy the list completely
+ * list but not so sure that the reference counts of all elements have
+ * dropped back to 1.
*/
void
-klpd_remove(klpd_reg_t **pp)
+klpd_freelist(klpd_reg_t **pp)
{
- klpd_reg_t *p = *pp;
- if (p == NULL)
- return;
- ASSERT(p->klpd_next == NULL);
- klpd_unlink(p);
- klpd_rele(p);
+ klpd_reg_t *p;
+
+ while ((p = *pp) != NULL) {
+ klpd_unlink(p);
+ klpd_rele(p);
+ }
}
/*
@@ -192,7 +189,7 @@ klpd_link(klpd_reg_t *p, klpd_reg_t **listp, boolean_t single)
static klpd_head_t *
klpd_marshall(klpd_reg_t *p, const priv_set_t *rq, va_list ap)
{
- char *comp;
+ char *tmp;
uint_t type;
vnode_t *vp;
size_t len = sizeof (priv_set_t) + sizeof (klpd_head_t);
@@ -214,10 +211,10 @@ klpd_marshall(klpd_reg_t *p, const priv_set_t *rq, va_list ap)
if (vp == NULL)
return (NULL);
- comp = va_arg(ap, char *);
+ tmp = va_arg(ap, char *);
- if (comp != NULL && *comp != '\0')
- clen = strlen(comp) + 1;
+ if (tmp != NULL && *tmp != '\0')
+ clen = strlen(tmp) + 1;
else
clen = 0;
@@ -242,7 +239,7 @@ klpd_marshall(klpd_reg_t *p, const priv_set_t *rq, va_list ap)
if (plen <= 2)
plen = 0;
kap->kla_str[plen] = '/';
- bcopy(comp, &kap->kla_str[plen + 1], clen);
+ bcopy(tmp, &kap->kla_str[plen + 1], clen);
}
break;
case KLPDARG_PORT:
@@ -636,7 +633,7 @@ klpd_unreg(int did, idtype_t type, id_t id)
if (kpp->kpj_klpd == NULL)
res = ESRCH;
else
- klpd_remove(&kpp->kpj_klpd);
+ klpd_freelist(&kpp->kpj_klpd);
mutex_exit(&klpd_mutex);
project_rele(kpp);
goto out;
@@ -721,3 +718,429 @@ crklpd_setreg(credklpd_t *crk, klpd_reg_t *new)
if (old != NULL)
klpd_rele(old);
}
+
+/* Allocate and register the pfexec specific callback */
+int
+pfexec_reg(int did)
+{
+ door_handle_t dh;
+ int err = secpolicy_pfexec_register(CRED());
+ klpd_reg_t *pfx;
+ door_info_t di;
+ zone_t *myzone = crgetzone(CRED());
+
+ if (err != 0)
+ return (set_errno(err));
+
+ dh = door_ki_lookup(did);
+ if (dh == NULL || door_ki_info(dh, &di) != 0)
+ return (set_errno(EBADF));
+
+ pfx = kmem_zalloc(sizeof (*pfx), KM_SLEEP);
+
+ pfx->klpd_door = dh;
+ pfx->klpd_door_pid = di.di_target;
+ pfx->klpd_ref = 1;
+ pfx->klpd_cred = NULL;
+ mutex_enter(&myzone->zone_lock);
+ pfx = klpd_link(pfx, &myzone->zone_pfexecd, B_TRUE);
+ mutex_exit(&myzone->zone_lock);
+ if (pfx != NULL)
+ klpd_rele(pfx);
+
+ return (0);
+}
+
+int
+pfexec_unreg(int did)
+{
+ door_handle_t dh;
+ int err = 0;
+ zone_t *myzone = crgetzone(CRED());
+ klpd_reg_t *pfd;
+
+ dh = door_ki_lookup(did);
+ if (dh == NULL)
+ return (set_errno(EBADF));
+
+ mutex_enter(&myzone->zone_lock);
+ pfd = myzone->zone_pfexecd;
+ if (pfd != NULL && pfd->klpd_door == dh) {
+ klpd_unlink(pfd);
+ } else {
+ pfd = NULL;
+ err = EINVAL;
+ }
+ mutex_exit(&myzone->zone_lock);
+ door_ki_rele(dh);
+ /*
+ * crfree() cannot be called with zone_lock held; it is called
+ * indirectly through closing the door handle
+ */
+ if (pfd != NULL)
+ klpd_rele(pfd);
+ if (err != 0)
+ return (set_errno(err));
+ return (0);
+}
+
+static int
+get_path(char *buf, const char *path, int len)
+{
+ size_t lc;
+ char *s;
+
+ if (len < 0)
+ len = strlen(path);
+
+ if (*path == '/' && len < MAXPATHLEN) {
+ (void) strcpy(buf, path);
+ return (0);
+ }
+ /*
+ * Build the pathname using the current directory + resolve pathname.
+ * The resolve pathname either starts with a normal component and
+ * we can just concatenate them or it starts with one
+ * or more ".." component and we can remove those; the
+ * last one cannot be a ".." and the current directory has
+ * more components than the number of ".." in the resolved pathname.
+ */
+ if (dogetcwd(buf, MAXPATHLEN) != 0)
+ return (-1);
+
+ lc = strlen(buf);
+
+ while (len > 3 && strncmp("../", path, 3) == 0) {
+ len -= 3;
+ path += 3;
+
+ s = strrchr(buf, '/');
+ if (s == NULL || s == buf)
+ return (-1);
+
+ *s = '\0';
+ lc = s - buf;
+ }
+ /* Add a "/" and a NUL */
+ if (lc < 2 || lc + len + 2 >= MAXPATHLEN)
+ return (-1);
+
+ buf[lc] = '/';
+ (void) strcpy(buf + lc + 1, path);
+
+ return (0);
+}
+
+/*
+ * Perform the pfexec upcall.
+ *
+ * The pfexec upcall is different from the klpd_upcall in that a failure
+ * will lead to a denial of execution.
+ */
+int
+pfexec_call(const cred_t *cr, struct pathname *rpnp, cred_t **pfcr,
+ boolean_t *scrub)
+{
+ klpd_reg_t *pfd;
+ pfexec_arg_t *pap;
+ pfexec_reply_t pr, *prp;
+ door_arg_t da;
+ int dres;
+ cred_t *ncr = NULL;
+ int err = -1;
+ priv_set_t *iset;
+ priv_set_t *lset;
+ zone_t *myzone = crgetzone(CRED());
+ size_t pasize = PFEXEC_ARG_SIZE(MAXPATHLEN);
+
+ /* Find registration */
+ mutex_enter(&myzone->zone_lock);
+ if ((pfd = myzone->zone_pfexecd) != NULL)
+ klpd_hold(pfd);
+ mutex_exit(&myzone->zone_lock);
+
+ if (pfd == NULL)
+ return (0);
+
+ if (pfd->klpd_door_pid == curproc->p_pid) {
+ klpd_rele(pfd);
+ return (0);
+ }
+
+ pap = kmem_zalloc(pasize, KM_SLEEP);
+
+ if (get_path(pap->pfa_path, rpnp->pn_path, rpnp->pn_pathlen) == -1)
+ goto out1;
+
+ pap->pfa_vers = PFEXEC_ARG_VERS;
+ pap->pfa_call = PFEXEC_EXEC_ATTRS;
+ pap->pfa_len = pasize;
+ pap->pfa_uid = crgetruid(cr);
+
+ da.data_ptr = (char *)pap;
+ da.data_size = pap->pfa_len;
+ da.desc_ptr = NULL;
+ da.desc_num = 0;
+ da.rbuf = (char *)&pr;
+ da.rsize = sizeof (pr);
+
+ while ((dres = door_ki_upcall(pfd->klpd_door, &da)) != 0) {
+ switch (dres) {
+ case EAGAIN:
+ delay(1);
+ continue;
+ case EINVAL:
+ case EBADF:
+ /* FALLTHROUGH */
+ case EINTR:
+ /* FALLTHROUGH */
+ default:
+ goto out;
+ }
+ }
+
+ prp = (pfexec_reply_t *)da.rbuf;
+ /*
+ * Check the size of the result and the alignment of the
+ * privilege sets.
+ */
+ if (da.rsize < sizeof (pr) ||
+ prp->pfr_ioff > da.rsize - sizeof (priv_set_t) ||
+ prp->pfr_loff > da.rsize - sizeof (priv_set_t) ||
+ (prp->pfr_loff & (sizeof (priv_chunk_t) - 1)) != 0 ||
+ (prp->pfr_loff & (sizeof (priv_chunk_t) - 1)) != 0)
+ goto out;
+
+ /*
+ * Get results:
+ * allow/allow with additional credentials/disallow[*]
+ *
+ * euid, uid, egid, gid, privs, and limitprivs
+ * We now have somewhat more flexibility we could even set E and P
+ * judiciously but that would break some currently valid assumptions
+ * [*] Disallow is not readily supported by always including
+ * the Basic Solaris User profile in all user's profiles.
+ */
+
+ if (!prp->pfr_allowed) {
+ err = EACCES;
+ goto out;
+ }
+ if (!prp->pfr_setcred) {
+ err = 0;
+ goto out;
+ }
+ ncr = crdup((cred_t *)cr);
+
+ /*
+ * Generate the new credential set scrubenv if ruid != euid (or set)
+ * the "I'm set-uid flag" but that is not inherited so scrubbing
+ * the environment is a requirement.
+ */
+ /* Set uids or gids, note that -1 will do the right thing */
+ if (crsetresuid(ncr, prp->pfr_ruid, prp->pfr_euid, prp->pfr_euid) != 0)
+ goto out;
+ if (crsetresgid(ncr, prp->pfr_rgid, prp->pfr_egid, prp->pfr_egid) != 0)
+ goto out;
+
+ *scrub = prp->pfr_scrubenv;
+
+ if (prp->pfr_clearflag)
+ CR_FLAGS(ncr) &= ~PRIV_PFEXEC;
+
+ /* We cannot exceed our Limit set, no matter what */
+ iset = PFEXEC_REPLY_IPRIV(prp);
+
+ if (iset != NULL) {
+ if (!priv_issubset(iset, &CR_LPRIV(ncr)))
+ goto out;
+ priv_union(iset, &CR_IPRIV(ncr));
+ }
+
+ /* Nor can we increate our Limit set itself */
+ lset = PFEXEC_REPLY_LPRIV(prp);
+
+ if (lset != NULL) {
+ if (!priv_issubset(lset, &CR_LPRIV(ncr)))
+ goto out;
+ CR_LPRIV(ncr) = *lset;
+ }
+
+ /* Exec will do the standard set operations */
+
+ err = 0;
+out:
+ if (da.rbuf != (char *)&pr)
+ kmem_free(da.rbuf, da.rsize);
+out1:
+ kmem_free(pap, pasize);
+ klpd_rele(pfd);
+ if (ncr != NULL) {
+ if (err == 0)
+ *pfcr = ncr;
+ else
+ crfree(ncr);
+ }
+ return (err);
+}
+
+int
+get_forced_privs(const cred_t *cr, const char *respn, priv_set_t *set)
+{
+ klpd_reg_t *pfd;
+ pfexec_arg_t *pap;
+ door_arg_t da;
+ int dres;
+ int err = -1;
+ priv_set_t *fset, pmem;
+ cred_t *zkcr;
+ zone_t *myzone = crgetzone(cr);
+ size_t pasize = PFEXEC_ARG_SIZE(MAXPATHLEN);
+
+ mutex_enter(&myzone->zone_lock);
+ if ((pfd = myzone->zone_pfexecd) != NULL)
+ klpd_hold(pfd);
+ mutex_exit(&myzone->zone_lock);
+
+ if (pfd == NULL)
+ return (-1);
+
+ if (pfd->klpd_door_pid == curproc->p_pid) {
+ klpd_rele(pfd);
+ return (0);
+ }
+
+ pap = kmem_zalloc(pasize, KM_SLEEP);
+
+ if (get_path(pap->pfa_path, respn, -1) == -1)
+ goto out1;
+
+ pap->pfa_vers = PFEXEC_ARG_VERS;
+ pap->pfa_call = PFEXEC_FORCED_PRIVS;
+ pap->pfa_len = pasize;
+ pap->pfa_uid = (uid_t)-1; /* Not relevant */
+
+ da.data_ptr = (char *)pap;
+ da.data_size = pap->pfa_len;
+ da.desc_ptr = NULL;
+ da.desc_num = 0;
+ da.rbuf = (char *)&pmem;
+ da.rsize = sizeof (pmem);
+
+ while ((dres = door_ki_upcall(pfd->klpd_door, &da)) != 0) {
+ switch (dres) {
+ case EAGAIN:
+ delay(1);
+ continue;
+ case EINVAL:
+ case EBADF:
+ case EINTR:
+ default:
+ goto out;
+ }
+ }
+
+ /*
+ * Check the size of the result, it's a privilege set.
+ */
+ if (da.rsize != sizeof (priv_set_t))
+ goto out;
+
+ fset = (priv_set_t *)da.rbuf;
+
+ /*
+ * We restrict the forced privileges with whatever is available in
+ * the current zone.
+ */
+ zkcr = zone_kcred();
+ priv_intersect(&CR_LPRIV(zkcr), fset);
+
+ /*
+ * But we fail if the forced privileges are not found in the current
+ * Limit set.
+ */
+ if (!priv_issubset(fset, &CR_LPRIV(cr))) {
+ err = EACCES;
+ } else if (!priv_isemptyset(fset)) {
+ err = 0;
+ *set = *fset;
+ }
+out:
+ if (da.rbuf != (char *)&pmem)
+ kmem_free(da.rbuf, da.rsize);
+out1:
+ kmem_free(pap, pasize);
+ klpd_rele(pfd);
+ return (err);
+}
+
+int
+check_user_privs(const cred_t *cr, const priv_set_t *set)
+{
+ klpd_reg_t *pfd;
+ pfexec_arg_t *pap;
+ door_arg_t da;
+ int dres;
+ int err = -1;
+ zone_t *myzone = crgetzone(cr);
+ size_t pasize = PFEXEC_ARG_SIZE(sizeof (priv_set_t));
+ uint32_t res;
+
+ mutex_enter(&myzone->zone_lock);
+ if ((pfd = myzone->zone_pfexecd) != NULL)
+ klpd_hold(pfd);
+ mutex_exit(&myzone->zone_lock);
+
+ if (pfd == NULL)
+ return (-1);
+
+ if (pfd->klpd_door_pid == curproc->p_pid) {
+ klpd_rele(pfd);
+ return (0);
+ }
+
+ pap = kmem_zalloc(pasize, KM_SLEEP);
+
+ *(priv_set_t *)&pap->pfa_buf = *set;
+
+ pap->pfa_vers = PFEXEC_ARG_VERS;
+ pap->pfa_call = PFEXEC_USER_PRIVS;
+ pap->pfa_len = pasize;
+ pap->pfa_uid = crgetruid(cr);
+
+ da.data_ptr = (char *)pap;
+ da.data_size = pap->pfa_len;
+ da.desc_ptr = NULL;
+ da.desc_num = 0;
+ da.rbuf = (char *)&res;
+ da.rsize = sizeof (res);
+
+ while ((dres = door_ki_upcall(pfd->klpd_door, &da)) != 0) {
+ switch (dres) {
+ case EAGAIN:
+ delay(1);
+ continue;
+ case EINVAL:
+ case EBADF:
+ case EINTR:
+ default:
+ goto out;
+ }
+ }
+
+ /*
+ * Check the size of the result.
+ */
+ if (da.rsize != sizeof (res))
+ goto out;
+
+ if (*(uint32_t *)da.rbuf == 1)
+ err = 0;
+out:
+ if (da.rbuf != (char *)&res)
+ kmem_free(da.rbuf, da.rsize);
+out1:
+ kmem_free(pap, pasize);
+ klpd_rele(pfd);
+ return (err);
+}
diff --git a/usr/src/uts/common/os/policy.c b/usr/src/uts/common/os/policy.c
index d6444e7fc3..c56ec6db92 100644
--- a/usr/src/uts/common/os/policy.c
+++ b/usr/src/uts/common/os/policy.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -147,6 +146,12 @@ int priv_basic_test = -1;
HAS_ALLPRIVS(cr) : \
PRIV_ISASSERT(&CR_OEPRIV(cr), pr))
+#define FAST_BASIC_CHECK(cr, priv) \
+ if (PRIV_ISASSERT(&CR_OEPRIV(cr), priv)) { \
+ DTRACE_PROBE2(priv__ok, int, priv, boolean_t, B_FALSE); \
+ return (0); \
+ }
+
/*
* Policy checking functions.
*
@@ -338,17 +343,28 @@ priv_policy_override(const cred_t *cr, int priv, boolean_t allzone, va_list ap)
}
static int
-priv_policy_override_set(const cred_t *cr, const priv_set_t *req, ...)
+priv_policy_override_set(const cred_t *cr, const priv_set_t *req, va_list ap)
{
- va_list ap;
-
+ if (CR_FLAGS(cr) & PRIV_PFEXEC)
+ return (check_user_privs(cr, req));
if (CR_FLAGS(cr) & PRIV_XPOLICY) {
- va_start(ap, req);
return (klpd_call(cr, req, ap));
}
return (-1);
}
+static int
+priv_policy_override_set_va(const cred_t *cr, const priv_set_t *req, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, req);
+ ret = priv_policy_override_set(cr, req, ap);
+ va_end(ap);
+ return (ret);
+}
+
/*
* Audit failure, log error message.
*/
@@ -418,7 +434,7 @@ int
priv_policy(const cred_t *cr, int priv, boolean_t allzone, int err,
const char *msg)
{
- return (priv_policy_va(cr, priv, allzone, err, msg, KLPDARG_NOMORE));
+ return (priv_policy_va(cr, priv, allzone, err, msg, KLPDARG_NONE));
}
/*
@@ -465,18 +481,24 @@ priv_policy_only(const cred_t *cr, int priv, boolean_t allzone)
* Check whether all privileges in the required set are present.
*/
static int
-secpolicy_require_set(const cred_t *cr, const priv_set_t *req, const char *msg)
+secpolicy_require_set(const cred_t *cr, const priv_set_t *req,
+ const char *msg, ...)
{
int priv;
int pfound = -1;
priv_set_t pset;
+ va_list ap;
+ int ret;
if (req == PRIV_FULLSET ? HAS_ALLPRIVS(cr) : priv_issubset(req,
&CR_OEPRIV(cr))) {
return (0);
}
- if (priv_policy_override_set(cr, req, KLPDARG_NOMORE) == 0)
+ va_start(ap, msg);
+ ret = priv_policy_override_set(cr, req, ap);
+ va_end(ap);
+ if (ret == 0)
return (0);
if (req == PRIV_FULLSET || priv_isfullset(req)) {
@@ -542,6 +564,9 @@ secpolicy_setpriority(const cred_t *cr)
/*
* Binding to a privileged port, port must be specified in host byte
* order.
+ * When adding a new privilege which allows binding to currently privileged
+ * ports, then you MUST also allow processes with PRIV_NET_PRIVADDR bind
+ * to these ports because of backward compatibility.
*/
int
secpolicy_net_privaddr(const cred_t *cr, in_port_t port, int proto)
@@ -555,10 +580,16 @@ secpolicy_net_privaddr(const cred_t *cr, in_port_t port, int proto)
case 139:
case 445:
/*
- * NBT and SMB ports, these are extra privileged ports,
- * allow bind only if the SYS_SMB privilege is present.
+ * NBT and SMB ports, these are normal privileged ports,
+ * allow bind only if the SYS_SMB or NET_PRIVADDR privilege
+ * is present.
+ * Try both, if neither is present return an error for
+ * priv SYS_SMB.
*/
- priv = PRIV_SYS_SMB;
+ if (PRIV_POLICY_ONLY(cr, PRIV_NET_PRIVADDR, B_FALSE))
+ priv = PRIV_NET_PRIVADDR;
+ else
+ priv = PRIV_SYS_SMB;
reason = "NBT or SMB port";
break;
@@ -684,8 +715,8 @@ secpolicy_fs_common(cred_t *cr, vnode_t *mvp, const vfs_t *vfsp,
if ((err = secpolicy_vnode_owner(cr, va.va_uid)) != 0)
return (err);
- if ((va.va_mode & VWRITE) == 0 &&
- secpolicy_vnode_access(cr, mvp, va.va_uid, VWRITE) != 0) {
+ if (secpolicy_vnode_access2(cr, mvp, va.va_uid, va.va_mode,
+ VWRITE) != 0) {
return (EACCES);
}
}
@@ -839,7 +870,6 @@ secpolicy_fs_linkdir(const cred_t *cr, const vfs_t *vfsp)
* Output: EACCES - if privilege check fails.
*/
-/* ARGSUSED */
int
secpolicy_vnode_access(const cred_t *cr, vnode_t *vp, uid_t owner, mode_t mode)
{
@@ -877,6 +907,116 @@ secpolicy_vnode_access(const cred_t *cr, vnode_t *vp, uid_t owner, mode_t mode)
}
/*
+ * Like secpolicy_vnode_access() but we get the actual wanted mode and the
+ * current mode of the file, not the missing bits.
+ */
+int
+secpolicy_vnode_access2(const cred_t *cr, vnode_t *vp, uid_t owner,
+ mode_t curmode, mode_t wantmode)
+{
+ mode_t mode;
+
+ /* Inline the basic privileges tests. */
+ if ((wantmode & VREAD) &&
+ !PRIV_ISASSERT(&CR_OEPRIV(cr), PRIV_FILE_READ) &&
+ priv_policy_va(cr, PRIV_FILE_READ, B_FALSE, EACCES, NULL,
+ KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE) != 0) {
+ return (EACCES);
+ }
+
+ if ((wantmode & VWRITE) &&
+ !PRIV_ISASSERT(&CR_OEPRIV(cr), PRIV_FILE_WRITE) &&
+ priv_policy_va(cr, PRIV_FILE_WRITE, B_FALSE, EACCES, NULL,
+ KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE) != 0) {
+ return (EACCES);
+ }
+
+ mode = ~curmode & wantmode;
+
+ if (mode == 0)
+ return (0);
+
+ if ((mode & VREAD) && priv_policy_va(cr, PRIV_FILE_DAC_READ, B_FALSE,
+ EACCES, NULL, KLPDARG_VNODE, vp, (char *)NULL,
+ KLPDARG_NOMORE) != 0) {
+ return (EACCES);
+ }
+
+ if (mode & VWRITE) {
+ boolean_t allzone;
+
+ if (owner == 0 && cr->cr_uid != 0)
+ allzone = B_TRUE;
+ else
+ allzone = B_FALSE;
+ if (priv_policy_va(cr, PRIV_FILE_DAC_WRITE, allzone, EACCES,
+ NULL, KLPDARG_VNODE, vp, (char *)NULL,
+ KLPDARG_NOMORE) != 0) {
+ return (EACCES);
+ }
+ }
+
+ if (mode & VEXEC) {
+ /*
+ * Directories use file_dac_search to override the execute bit.
+ */
+ int p = vp->v_type == VDIR ? PRIV_FILE_DAC_SEARCH :
+ PRIV_FILE_DAC_EXECUTE;
+
+ return (priv_policy_va(cr, p, B_FALSE, EACCES, NULL,
+ KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE));
+ }
+ return (0);
+}
+
+/*
+ * This is a special routine for ZFS; it is used to determine whether
+ * any of the privileges in effect allow any form of access to the
+ * file. There's no reason to audit this or any reason to record
+ * this. More work is needed to do the "KPLD" stuff.
+ */
+int
+secpolicy_vnode_any_access(const cred_t *cr, vnode_t *vp, uid_t owner)
+{
+ static int privs[] = {
+ PRIV_FILE_OWNER,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_WRITE,
+ PRIV_FILE_DAC_EXECUTE,
+ PRIV_FILE_DAC_SEARCH,
+ };
+ int i;
+
+ /* Same as secpolicy_vnode_setdac */
+ if (owner == cr->cr_uid)
+ return (0);
+
+ for (i = 0; i < sizeof (privs)/sizeof (int); i++) {
+ boolean_t allzone = B_FALSE;
+ int priv;
+
+ switch (priv = privs[i]) {
+ case PRIV_FILE_DAC_EXECUTE:
+ if (vp->v_type == VDIR)
+ continue;
+ break;
+ case PRIV_FILE_DAC_SEARCH:
+ if (vp->v_type != VDIR)
+ continue;
+ break;
+ case PRIV_FILE_DAC_WRITE:
+ case PRIV_FILE_OWNER:
+ /* We know here that if owner == 0, that cr_uid != 0 */
+ allzone = owner == 0;
+ break;
+ }
+ if (PRIV_POLICY_CHOICE(cr, priv, allzone))
+ return (0);
+ }
+ return (EPERM);
+}
+
+/*
* Name: secpolicy_vnode_setid_modify()
*
* Normal: verify that subject can set the file setid flags.
@@ -1407,14 +1547,19 @@ secpolicy_audit_modify(const cred_t *cr)
* "Least" of the two privileges on error.
*/
int
-secpolicy_audit_getattr(const cred_t *cr)
+secpolicy_audit_getattr(const cred_t *cr, boolean_t checkonly)
{
- if (!PRIV_POLICY_ONLY(cr, PRIV_SYS_AUDIT, B_FALSE)) {
- return (PRIV_POLICY(cr, PRIV_PROC_AUDIT, B_FALSE, EPERM,
- NULL));
- } else {
- return (PRIV_POLICY(cr, PRIV_SYS_AUDIT, B_FALSE, EPERM, NULL));
- }
+ int priv;
+
+ if (PRIV_POLICY_ONLY(cr, PRIV_SYS_AUDIT, B_FALSE))
+ priv = PRIV_SYS_AUDIT;
+ else
+ priv = PRIV_PROC_AUDIT;
+
+ if (checkonly)
+ return (!PRIV_POLICY_ONLY(cr, priv, B_FALSE));
+ else
+ return (PRIV_POLICY(cr, priv, B_FALSE, EPERM, NULL));
}
@@ -1582,7 +1727,7 @@ secpolicy_zone_config(const cred_t *cr)
* Require all privileges to avoid possibility of privilege
* escalation.
*/
- return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
+ return (secpolicy_require_set(cr, PRIV_FULLSET, NULL, KLPDARG_NONE));
}
/*
@@ -1857,12 +2002,20 @@ secpolicy_tasksys(const cred_t *cr)
return (PRIV_POLICY(cr, PRIV_PROC_TASKID, B_FALSE, EPERM, NULL));
}
+int
+secpolicy_pfexec_register(const cred_t *cr)
+{
+ return (PRIV_POLICY(cr, PRIV_SYS_ADMIN, B_TRUE, EPERM, NULL));
+}
+
/*
* Basic privilege checks.
*/
int
secpolicy_basic_exec(const cred_t *cr, vnode_t *vp)
{
+ FAST_BASIC_CHECK(cr, PRIV_PROC_EXEC);
+
return (priv_policy_va(cr, PRIV_PROC_EXEC, B_FALSE, EPERM, NULL,
KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE));
}
@@ -1870,12 +2023,16 @@ secpolicy_basic_exec(const cred_t *cr, vnode_t *vp)
int
secpolicy_basic_fork(const cred_t *cr)
{
+ FAST_BASIC_CHECK(cr, PRIV_PROC_FORK);
+
return (PRIV_POLICY(cr, PRIV_PROC_FORK, B_FALSE, EPERM, NULL));
}
int
secpolicy_basic_proc(const cred_t *cr)
{
+ FAST_BASIC_CHECK(cr, PRIV_PROC_SESSION);
+
return (PRIV_POLICY(cr, PRIV_PROC_SESSION, B_FALSE, EPERM, NULL));
}
@@ -1900,15 +2057,39 @@ secpolicy_basic_procinfo(const cred_t *cr, proc_t *tp, proc_t *sp)
int
secpolicy_basic_link(const cred_t *cr)
{
+ FAST_BASIC_CHECK(cr, PRIV_FILE_LINK_ANY);
+
return (PRIV_POLICY(cr, PRIV_FILE_LINK_ANY, B_FALSE, EPERM, NULL));
}
int
secpolicy_basic_net_access(const cred_t *cr)
{
+ FAST_BASIC_CHECK(cr, PRIV_NET_ACCESS);
+
return (PRIV_POLICY(cr, PRIV_NET_ACCESS, B_FALSE, EACCES, NULL));
}
+/* ARGSUSED */
+int
+secpolicy_basic_file_read(const cred_t *cr, vnode_t *vp, const char *pn)
+{
+ FAST_BASIC_CHECK(cr, PRIV_FILE_READ);
+
+ return (priv_policy_va(cr, PRIV_FILE_READ, B_FALSE, EACCES, NULL,
+ KLPDARG_VNODE, vp, (char *)pn, KLPDARG_NOMORE));
+}
+
+/* ARGSUSED */
+int
+secpolicy_basic_file_write(const cred_t *cr, vnode_t *vp, const char *pn)
+{
+ FAST_BASIC_CHECK(cr, PRIV_FILE_WRITE);
+
+ return (priv_policy_va(cr, PRIV_FILE_WRITE, B_FALSE, EACCES, NULL,
+ KLPDARG_VNODE, vp, (char *)pn, KLPDARG_NOMORE));
+}
+
/*
* Additional device protection.
*
@@ -1969,7 +2150,7 @@ secpolicy_spec_open(const cred_t *cr, struct vnode *vp, int oflag)
priv_addset(&pset, PRIV_SYS_NET_CONFIG);
}
- err = secpolicy_require_set(cr, &pset, "devpolicy");
+ err = secpolicy_require_set(cr, &pset, "devpolicy", KLPDARG_NONE);
dpfree(plcy);
return (err);
@@ -2000,7 +2181,8 @@ secpolicy_modctl(const cred_t *cr, int cmd)
return (0);
case MODLOAD:
case MODSETDEVPOLICY:
- return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
+ return (secpolicy_require_set(cr, PRIV_FULLSET, NULL,
+ KLPDARG_NONE));
default:
return (secpolicy_sys_config(cr, B_FALSE));
}
@@ -2025,7 +2207,7 @@ secpolicy_power_mgmt(const cred_t *cr)
int
secpolicy_sti(const cred_t *cr)
{
- return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
+ return (secpolicy_require_set(cr, PRIV_FULLSET, NULL, KLPDARG_NONE));
}
boolean_t
@@ -2146,7 +2328,7 @@ secpolicy_gart_map(const cred_t *cr)
int
secpolicy_zinject(const cred_t *cr)
{
- return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
+ return (secpolicy_require_set(cr, PRIV_FULLSET, NULL, KLPDARG_NONE));
}
/*
@@ -2205,7 +2387,7 @@ secpolicy_sadopen(const cred_t *credp)
else
priv_addset(&pset, PRIV_SYS_IP_CONFIG);
- return (secpolicy_require_set(credp, &pset, "devpolicy"));
+ return (secpolicy_require_set(credp, &pset, "devpolicy", KLPDARG_NONE));
}
@@ -2226,7 +2408,7 @@ secpolicy_require_privs(const cred_t *cr, const priv_set_t *nset)
priv_inverse(&rqd);
priv_intersect(nset, &rqd);
- return (secpolicy_require_set(cr, &rqd, NULL));
+ return (secpolicy_require_set(cr, &rqd, NULL, KLPDARG_NONE));
}
/*
diff --git a/usr/src/uts/common/os/priv_defs b/usr/src/uts/common/os/priv_defs
index ef77206388..9ec62db828 100644
--- a/usr/src/uts/common/os/priv_defs
+++ b/usr/src/uts/common/os/priv_defs
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*
INSERT COMMENT
*/
@@ -136,6 +135,10 @@ privilege PRIV_FILE_OWNER
permission bits or ACL except for the set-uid and set-gid
bits.
+basic privilege PRIV_FILE_READ
+
+ Allows a process to read objects in the filesystem.
+
privilege PRIV_FILE_SETID
Allows a process to change the ownership of a file or write to
@@ -157,6 +160,10 @@ privilege PRIV_FILE_UPGRADE_SL
This privilege is interpreted only if the system is configured
with Trusted Extensions.
+basic privilege PRIV_FILE_WRITE
+
+ Allows a process to modify objects in the filesystem.
+
privilege PRIV_GRAPHICS_ACCESS
Allows a process to make privileged ioctls to graphics devices.
diff --git a/usr/src/uts/common/os/project.c b/usr/src/uts/common/os/project.c
index 7d10ec9370..98b5b93683 100644
--- a/usr/src/uts/common/os/project.c
+++ b/usr/src/uts/common/os/project.c
@@ -19,12 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/project.h>
#include <sys/modhash.h>
#include <sys/modctl.h>
@@ -361,7 +358,7 @@ project_rele(kproject_t *p)
project_kstat_delete(p);
if (p->kpj_klpd != NULL)
- klpd_remove(&p->kpj_klpd);
+ klpd_freelist(&p->kpj_klpd);
if (mod_hash_destroy(projects_hash, (mod_hash_key_t)p))
panic("unable to delete project %d zone %d", p->kpj_id,
diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c
index 4f08e77f59..1d3cfc8f51 100644
--- a/usr/src/uts/common/os/zone.c
+++ b/usr/src/uts/common/os/zone.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -227,6 +226,7 @@
#include <sys/vmparam.h>
#include <sys/corectl.h>
#include <sys/ipc_impl.h>
+#include <sys/klpd.h>
#include <sys/door.h>
#include <sys/cpuvar.h>
@@ -2043,6 +2043,8 @@ zone_free(zone_t *zone)
kmem_free(zone->zone_bootargs, strlen(zone->zone_bootargs) + 1);
if (zone->zone_initname != NULL)
kmem_free(zone->zone_initname, strlen(zone->zone_initname) + 1);
+ if (zone->zone_pfexecd != NULL)
+ klpd_freelist(&zone->zone_pfexecd);
id_free(zoneid_space, zone->zone_id);
mutex_destroy(&zone->zone_lock);
cv_destroy(&zone->zone_cv);
@@ -4479,6 +4481,12 @@ zone_destroy(zoneid_t zoneid)
/* Get rid of the zone's kstats */
zone_kstat_delete(zone);
+ /* remove the pfexecd doors */
+ if (zone->zone_pfexecd != NULL) {
+ klpd_freelist(&zone->zone_pfexecd);
+ zone->zone_pfexecd = NULL;
+ }
+
/* free brand specific data */
if (ZONE_IS_BRANDED(zone))
ZBROP(zone)->b_free_brand_data(zone);
diff --git a/usr/src/uts/common/sys/exec.h b/usr/src/uts/common/sys/exec.h
index d246d5e885..d36bc20481 100644
--- a/usr/src/uts/common/sys/exec.h
+++ b/usr/src/uts/common/sys/exec.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -105,6 +104,8 @@ typedef struct uarg {
char *brandname;
char *auxp_auxflags; /* addr of auxflags auxv on the user stack */
char *auxp_brand; /* address of first brand auxv on user stack */
+ cred_t *pfcred;
+ boolean_t scrubenv;
} uarg_t;
/*
diff --git a/usr/src/uts/common/sys/fs/ufs_acl.h b/usr/src/uts/common/sys/fs/ufs_acl.h
index d1849a4d8e..a373384090 100644
--- a/usr/src/uts/common/sys/fs/ufs_acl.h
+++ b/usr/src/uts/common/sys/fs/ufs_acl.h
@@ -19,15 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_FS_UFS_ACL_H
#define _SYS_FS_UFS_ACL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/cred.h>
#include <sys/vfs.h>
@@ -162,8 +159,8 @@ typedef struct ufs_fsd {
#define ACL_CHECK 0x01
#define DEF_ACL_CHECK 0x02
-#define MODE_CHECK(O, M, PERM, C, I) ((((M) & (PERM)) == (M)) ? 0 : \
- secpolicy_vnode_access(C, ITOV(I), O, (M) & ~(PERM)))
+#define MODE_CHECK(O, M, PERM, C, I) \
+ secpolicy_vnode_access2(C, ITOV(I), O, (PERM), M)
/*
* Check that the file type is one that accepts ACLs
diff --git a/usr/src/uts/common/sys/klpd.h b/usr/src/uts/common/sys/klpd.h
index 535af85f89..32769f438f 100644
--- a/usr/src/uts/common/sys/klpd.h
+++ b/usr/src/uts/common/sys/klpd.h
@@ -19,15 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_KLPD_H
#define _SYS_KLPD_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/priv.h>
#include <sys/procset.h>
@@ -61,11 +58,16 @@ struct credklpd;
int klpd_reg(int, idtype_t, id_t, priv_set_t *);
int klpd_unreg(int, idtype_t, id_t);
-void klpd_remove(struct klpd_reg **);
+void klpd_freelist(struct klpd_reg **);
void klpd_rele(struct klpd_reg *);
int klpd_call(const cred_t *, const priv_set_t *, va_list);
void crklpd_hold(struct credklpd *);
void crklpd_rele(struct credklpd *);
+int pfexec_reg(int);
+int pfexec_unreg(int);
+int pfexec_call(const cred_t *, struct pathname *, cred_t **, boolean_t *);
+int get_forced_privs(const cred_t *, const char *, priv_set_t *);
+int check_user_privs(const cred_t *, const priv_set_t *);
#endif /* _KERNEL */
@@ -95,6 +97,50 @@ typedef struct klpd_arg {
#define kla_int kla_data.__idata
#define kla_uint kla_data.__uidata
+#define PFEXEC_ARG_VERS 0x1
+#define PFEXEC_EXEC_ATTRS 0x1 /* pfexec_reply_t */
+#define PFEXEC_FORCED_PRIVS 0x2 /* priv_set_t */
+#define PFEXEC_USER_PRIVS 0x3 /* uint32_t */
+
+#define PFEXEC_ARG_SIZE(bufsize) \
+ (offsetof(pfexec_arg_t, pfa_data) + (bufsize))
+
+typedef struct pfexec_arg {
+ uint_t pfa_vers; /* Caller version */
+ uint_t pfa_call; /* Call type */
+ uint_t pfa_len; /* Length of data */
+ uid_t pfa_uid; /* Real uid of subject */
+ union {
+ char __pfa_path[1];
+ uint32_t __pfa_buf[1];
+ } pfa_data;
+} pfexec_arg_t;
+
+#define pfa_path pfa_data.__pfa_path
+#define pfa_buf pfa_data.__pfa_buf
+
+#define PFEXEC_NOTSET ((uid_t)-1)
+
+typedef struct pfexec_reply {
+ uint_t pfr_vers;
+ uint_t pfr_len;
+ uid_t pfr_ruid, pfr_euid;
+ gid_t pfr_rgid, pfr_egid;
+ boolean_t pfr_setcred;
+ boolean_t pfr_scrubenv;
+ boolean_t pfr_clearflag;
+ boolean_t pfr_allowed;
+ uint_t pfr_ioff;
+ uint_t pfr_loff;
+} pfexec_reply_t;
+
+#define PFEXEC_REPLY_IPRIV(pfr) \
+ ((pfr)->pfr_ioff ? (priv_set_t *)((char *)(pfr) + (pfr)->pfr_ioff) \
+ : (priv_set_t *)0)
+#define PFEXEC_REPLY_LPRIV(pfr) \
+ ((pfr)->pfr_loff ? (priv_set_t *)((char *)(pfr) + (pfr)->pfr_loff) \
+ : (priv_set_t *)0)
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/policy.h b/usr/src/uts/common/sys/policy.h
index 3bbb416060..1703b7bec9 100644
--- a/usr/src/uts/common/sys/policy.h
+++ b/usr/src/uts/common/sys/policy.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_POLICY_H
@@ -74,7 +73,7 @@ int secpolicy_acct(const cred_t *);
int secpolicy_require_privs(const cred_t *, const struct priv_set *);
int secpolicy_allow_setid(const cred_t *, uid_t, boolean_t);
int secpolicy_audit_config(const cred_t *);
-int secpolicy_audit_getattr(const cred_t *);
+int secpolicy_audit_getattr(const cred_t *, boolean_t);
int secpolicy_audit_modify(const cred_t *);
int secpolicy_blacklist(const cred_t *);
int secpolicy_chroot(const cred_t *);
@@ -120,6 +119,7 @@ boolean_t secpolicy_net_reply_equal(const cred_t *);
int secpolicy_newproc(const cred_t *);
int secpolicy_nfs(const cred_t *);
int secpolicy_pcfs_modify_bootpartition(const cred_t *);
+int secpolicy_pfexec_register(const cred_t *);
int secpolicy_ponline(const cred_t *);
int secpolicy_pool(const cred_t *);
int secpolicy_power_mgmt(const cred_t *);
@@ -148,6 +148,8 @@ int secpolicy_sys_devices(const cred_t *);
int secpolicy_systeminfo(const cred_t *);
int secpolicy_tasksys(const cred_t *);
int secpolicy_vnode_access(const cred_t *, vnode_t *, uid_t, mode_t);
+int secpolicy_vnode_access2(const cred_t *, vnode_t *, uid_t, mode_t, mode_t);
+int secpolicy_vnode_any_access(const cred_t *, vnode_t *, uid_t);
int secpolicy_vnode_chown(const cred_t *, uid_t);
int secpolicy_vnode_create_gid(const cred_t *);
int secpolicy_vnode_owner(const cred_t *, uid_t);
@@ -171,6 +173,8 @@ int secpolicy_xvm_control(const cred_t *);
int secpolicy_basic_exec(const cred_t *, vnode_t *);
int secpolicy_basic_fork(const cred_t *);
int secpolicy_basic_link(const cred_t *);
+int secpolicy_basic_file_read(const cred_t *, vnode_t *, const char *);
+int secpolicy_basic_file_write(const cred_t *, vnode_t *, const char *);
int secpolicy_basic_net_access(const cred_t *);
int secpolicy_basic_proc(const cred_t *);
int secpolicy_basic_procinfo(const cred_t *, struct proc *, struct proc *);
diff --git a/usr/src/uts/common/sys/priv.h b/usr/src/uts/common/sys/priv.h
index 2683446bd2..49beaf156d 100644
--- a/usr/src/uts/common/sys/priv.h
+++ b/usr/src/uts/common/sys/priv.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_PRIV_H
@@ -82,6 +81,9 @@ typedef enum priv_op {
#define PRIVSYS_ISSETUGID 5
#define PRIVSYS_KLPD_REG 6
#define PRIVSYS_KLPD_UNREG 7
+#define PRIVSYS_PFEXEC_REG 8
+#define PRIVSYS_PFEXEC_UNREG 9
+
/*
* Maximum length of a user defined privilege name.
@@ -137,10 +139,11 @@ typedef struct priv_impl_info {
#define NET_MAC_AWARE_INHERIT 0x0020 /* Inherit MAC aware */
#define PRIV_AWARE_RESET 0x0040 /* Reset on setuid() */
#define PRIV_XPOLICY 0x0080 /* Extended policy */
+#define PRIV_PFEXEC 0x0100 /* As if pfexec'ed */
/* user-settable flags: */
#define PRIV_USER (PRIV_DEBUG | NET_MAC_AWARE | NET_MAC_AWARE_INHERIT |\
- PRIV_XPOLICY | PRIV_AWARE_RESET)
+ PRIV_XPOLICY | PRIV_AWARE_RESET | PRIV_PFEXEC)
/*
* Header of the privilege info data structure; multiple structures can
diff --git a/usr/src/uts/common/sys/zone.h b/usr/src/uts/common/sys/zone.h
index eb6317cf15..ead3f94774 100644
--- a/usr/src/uts/common/sys/zone.h
+++ b/usr/src/uts/common/sys/zone.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_ZONE_H
@@ -336,6 +335,7 @@ typedef struct zone {
* zone_ntasks
* zone_flags
* zone_zsd
+ * zone_pfexecd
*/
kmutex_t zone_lock;
/*
@@ -441,6 +441,8 @@ typedef struct zone {
*/
struct mntelem *zone_mntfs_db;
krwlock_t zone_mntfs_db_lock;
+
+ struct klpd_reg *zone_pfexecd;
} zone_t;
/*
diff --git a/usr/src/uts/common/syscall/auditsys.c b/usr/src/uts/common/syscall/auditsys.c
index 43b7df42b9..2b0f535d57 100644
--- a/usr/src/uts/common/syscall/auditsys.c
+++ b/usr/src/uts/common/syscall/auditsys.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/systm.h>
@@ -106,7 +105,7 @@ getauid(caddr_t auid_p)
{
const auditinfo_addr_t *ainfo;
- if (secpolicy_audit_getattr(CRED()) != 0)
+ if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
return (EPERM);
ainfo = crgetauinfo(CRED());
@@ -171,7 +170,7 @@ getaudit(caddr_t info_p)
const auditinfo_addr_t *ainfo;
model_t model;
- if (secpolicy_audit_getattr(CRED()) != 0)
+ if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
return (EPERM);
model = get_udatamodel();
@@ -220,7 +219,7 @@ getaudit_addr(caddr_t info_p, int len)
const auditinfo_addr_t *ainfo;
model_t model;
- if (secpolicy_audit_getattr(CRED()) != 0)
+ if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
return (EPERM);
model = get_udatamodel();
@@ -1344,7 +1343,7 @@ auditctl(
case A_GETPOLICY:
case A_GETQCTRL:
case A_GETSTAT:
- if (secpolicy_audit_getattr(CRED()) != 0)
+ if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
return (EPERM);
break;
default:
diff --git a/usr/src/uts/common/syscall/ppriv.c b/usr/src/uts/common/syscall/ppriv.c
index 14858710d9..bf42dc9810 100644
--- a/usr/src/uts/common/syscall/ppriv.c
+++ b/usr/src/uts/common/syscall/ppriv.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/param.h>
@@ -253,7 +252,7 @@ setpflags(uint_t flag, uint_t val, cred_t *tcr)
if (val > 1 || (flag != PRIV_DEBUG && flag != PRIV_AWARE &&
flag != NET_MAC_AWARE && flag != NET_MAC_AWARE_INHERIT &&
flag != __PROC_PROTECT && flag != PRIV_XPOLICY &&
- flag != PRIV_AWARE_RESET)) {
+ flag != PRIV_AWARE_RESET && flag != PRIV_PFEXEC)) {
return (EINVAL);
}
@@ -360,7 +359,8 @@ getpflags(uint_t flag, const cred_t *cr)
{
if (flag != PRIV_DEBUG && flag != PRIV_AWARE &&
flag != NET_MAC_AWARE && flag != NET_MAC_AWARE_INHERIT &&
- flag != PRIV_XPOLICY && flag != PRIV_AWARE_RESET)
+ flag != PRIV_XPOLICY && flag != PRIV_PFEXEC &&
+ flag != PRIV_AWARE_RESET)
return ((uint_t)-1);
return ((CR_FLAGS(cr) & flag) != 0);
@@ -402,6 +402,10 @@ privsys(int code, priv_op_t op, priv_ptype_t type, void *buf, size_t bufsize,
buf));
case PRIVSYS_KLPD_UNREG:
return ((int)klpd_unreg((int)op, (idtype_t)itype, (id_t)type));
+ case PRIVSYS_PFEXEC_REG:
+ return ((int)pfexec_reg((int)op));
+ case PRIVSYS_PFEXEC_UNREG:
+ return ((int)pfexec_unreg((int)op));
}
return (set_errno(EINVAL));
}
diff --git a/usr/src/uts/common/syscall/uid.c b/usr/src/uts/common/syscall/uid.c
index e3aa0a2dd2..2841892ff4 100644
--- a/usr/src/uts/common/syscall/uid.c
+++ b/usr/src/uts/common/syscall/uid.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -133,6 +132,11 @@ retry_locked:
newcr->cr_ruid = uid;
newcr->cr_suid = uid;
newcr->cr_uid = uid;
+
+ /* Remove the PRIV_PFEXEC, we changed the real uid. */
+ if (uidchge)
+ CR_FLAGS(newcr) &= ~PRIV_PFEXEC;
+
crsetsid(newcr, ksp, KSID_USER);
priv_reset_PA(newcr, B_TRUE);
@@ -345,6 +349,10 @@ retry_locked:
crsetsid(newcr, ksp, KSID_USER);
}
if (ruid != -1) {
+ /* Remove the PRIV_PFEXEC, we changed the real uid. */
+ if (uidchge)
+ CR_FLAGS(newcr) &= ~PRIV_PFEXEC;
+
oldruid = newcr->cr_ruid;
newcr->cr_ruid = ruid;
ASSERT(ruid != oldruid ? uidchge : 1);