summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorCasper H.S. Dik <Casper.Dik@Sun.COM>2010-04-28 10:01:37 +0200
committerCasper H.S. Dik <Casper.Dik@Sun.COM>2010-04-28 10:01:37 +0200
commit134a1f4e3289b54e0f980e9cf05352e419a60bee (patch)
tree792d1e39f7d9299df1f67c1681a02daa1b734878 /usr/src
parent2e98bdabdfa935eb368c090f1cecbba5619c88ee (diff)
downloadillumos-joyent-134a1f4e3289b54e0f980e9cf05352e419a60bee.tar.gz
PSARC 2009/377 In-kernel pfexec implementation.
PSARC 2009/378 Basic File Privileges PSARC 2010/072 RBAC update: user attrs from profiles 4912090 pfzsh(1) should exist 4912093 pfbash(1) should exist 4912096 pftcsh(1) should exist 6440298 Expand the basic privilege set in order to restrict file access 6859862 Move pfexec into the kernel 6919171 cred_t sidesteps kmem_debug; we need to be able to detect bad hold/free when they occur 6923721 The new SYS_SMB privilege is not backward compatible 6937562 autofs doesn't remove its door when the zone shuts down 6937727 Zones stuck on deathrow; netstack_zone keeps a credential reference to the zone 6940159 Implement PSARC 2010/072
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);