summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorrd117015 <none@none>2007-02-20 10:39:20 -0800
committerrd117015 <none@none>2007-02-20 10:39:20 -0800
commit532877c46d04a2d0b254f9b5797720078adcea07 (patch)
tree6a099b60988ee5b9c2a654492f35be5dce1ffee8 /usr/src/lib
parent0a9f9c2a7d4d961e3ed3221accb2c04919531d23 (diff)
downloadillumos-joyent-532877c46d04a2d0b254f9b5797720078adcea07.tar.gz
PSARC 2006/554 setproject(3PROJECT) defining, and enhancing behaviour
6194864 simultaneous setproject()'s on the same project can fail to set rctl 6449567 setproject(3PROJECT) deletes resource controls set through prctl(1M) 6450539 projmod(1M) does not provide a mechanism to refresh "in-core" enforced resource controls 6491754 project.max-contracts should not allow basic privileges 6491804 task.final project property is not honoured if pools are not enabled
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/common/inc/c_synonyms.h3
-rw-r--r--usr/src/lib/libc/inc/synonyms.h3
-rw-r--r--usr/src/lib/libc/port/llib-lc3
-rw-r--r--usr/src/lib/libc/port/mapfile-vers2
-rw-r--r--usr/src/lib/libc/port/sys/rctlsys.c15
-rw-r--r--usr/src/lib/libproc/common/libproc.h4
-rw-r--r--usr/src/lib/libproc/common/llib-lproc9
-rw-r--r--usr/src/lib/libproc/common/mapfile-vers3
-rw-r--r--usr/src/lib/libproc/common/pr_getrctl.c85
-rw-r--r--usr/src/lib/libproject/common/setproject.c169
10 files changed, 227 insertions, 69 deletions
diff --git a/usr/src/lib/common/inc/c_synonyms.h b/usr/src/lib/common/inc/c_synonyms.h
index 581f55150f..d652cc06c2 100644
--- a/usr/src/lib/common/inc/c_synonyms.h
+++ b/usr/src/lib/common/inc/c_synonyms.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -800,6 +800,7 @@ extern "C" {
#define setppriv _setppriv
#define setpwent _setpwent
#define setrctl _setrctl
+#define setprojrctl _setprojrctl
#define setregid _setregid
#define setreuid _setreuid
#define setrlimit _setrlimit
diff --git a/usr/src/lib/libc/inc/synonyms.h b/usr/src/lib/libc/inc/synonyms.h
index faa9d33034..209d7f6063 100644
--- a/usr/src/lib/libc/inc/synonyms.h
+++ b/usr/src/lib/libc/inc/synonyms.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -917,6 +917,7 @@ extern "C" {
#define setpgid _setpgid
#define setpgrp _setpgrp
#define setppriv _setppriv
+#define setprojrctl _setprojrctl
#define setpwent _setpwent
#define setrctl _setrctl
#define setregid _setregid
diff --git a/usr/src/lib/libc/port/llib-lc b/usr/src/lib/libc/port/llib-lc
index 169b444f6a..cff6f24c5d 100644
--- a/usr/src/lib/libc/port/llib-lc
+++ b/usr/src/lib/libc/port/llib-lc
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1348,6 +1348,7 @@ int getrctl(const char *name, rctlblk_t *old_rblk, rctlblk_t *new_rblk,
int setrctl(const char *name, rctlblk_t *old_rblk, rctlblk_t *new_rblk,
int flags);
/* (private functions) */
+int setprojrctl(const char *name, rctlblk_t *new_rblk, size_t size, int flags);
int rctlctl(const char *, rctlblk_t *, int);
size_t rctllist(char *, size_t);
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index 560ac9d878..1f3fdc9d6a 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -1989,6 +1989,8 @@ SUNWprivate_1.1 {
_setgrent;
_setlogmask;
_setpwent;
+ setprojrctl;
+ _setprojrctl;
_setregid;
_setreuid;
setsigacthandler;
diff --git a/usr/src/lib/libc/port/sys/rctlsys.c b/usr/src/lib/libc/port/sys/rctlsys.c
index e47511ac2a..9e395d3048 100644
--- a/usr/src/lib/libc/port/sys/rctlsys.c
+++ b/usr/src/lib/libc/port/sys/rctlsys.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,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,6 +29,7 @@
#pragma weak getrctl = _getrctl
#pragma weak rctllist = _rctllist
#pragma weak rctlctl = _rctlctl
+#pragma weak setprojrctl = _setprojrctl
#include "synonyms.h"
#include <sys/types.h>
@@ -71,3 +71,10 @@ rctlctl(const char *name, rctlblk_t *rblk, int flags)
{
return (syscall(SYS_rctlsys, 3, name, rblk, NULL, 0, flags));
}
+
+int
+setprojrctl(const char *name, rctlblk_t *new_rblk, size_t size, int flags)
+{
+ return (syscall(SYS_rctlsys,
+ 4, name, NULL, new_rblk, size, flags));
+}
diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h
index 07e58fa05c..d12fda05e3 100644
--- a/usr/src/lib/libproc/common/libproc.h
+++ b/usr/src/lib/libproc/common/libproc.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -325,6 +325,8 @@ extern int pr_getrlimit(struct ps_prochandle *,
int, struct rlimit *);
extern int pr_setrlimit(struct ps_prochandle *,
int, const struct rlimit *);
+extern int pr_setprojrctl(struct ps_prochandle *, const char *,
+ rctlblk_t *, size_t, int);
#if defined(_LARGEFILE64_SOURCE)
extern int pr_getrlimit64(struct ps_prochandle *,
int, struct rlimit64 *);
diff --git a/usr/src/lib/libproc/common/llib-lproc b/usr/src/lib/libproc/common/llib-lproc
index 015de9ca0e..b9eff09617 100644
--- a/usr/src/lib/libproc/common/llib-lproc
+++ b/usr/src/lib/libproc/common/llib-lproc
@@ -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.
@@ -23,7 +22,7 @@
/* PROTOLIB1 */
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -248,6 +247,8 @@ int pr_getrctl(struct ps_prochandle *Pr, const char *rname,
rctlblk_t *old_blk, rctlblk_t *new_blk, int rflag);
int pr_setrctl(struct ps_prochandle *Pr, const char *rname,
rctlblk_t *old_blk, rctlblk_t *new_blk, int rflag);
+int pr_setprojrctl(struct ps_prochandle *Pr, const char *rname,
+ rctlblk_t *new_blk, size_t size, int rflag);
/* pr_getrlimit.c */
int pr_getrlimit(struct ps_prochandle *Pr,
diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers
index ef256570ce..758f43d99f 100644
--- a/usr/src/lib/libproc/common/mapfile-vers
+++ b/usr/src/lib/libproc/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -208,6 +208,7 @@ SUNWprivate_1.1 {
pr_pset_bind;
pr_rename;
pr_setitimer;
+ pr_setprojrctl;
pr_setrctl;
pr_setrlimit;
pr_setrlimit64;
diff --git a/usr/src/lib/libproc/common/pr_getrctl.c b/usr/src/lib/libproc/common/pr_getrctl.c
index d54fc228a6..9cbf7dfa0c 100644
--- a/usr/src/lib/libproc/common/pr_getrctl.c
+++ b/usr/src/lib/libproc/common/pr_getrctl.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,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -33,6 +32,7 @@
#include <errno.h>
#include <strings.h>
#include "libproc.h"
+#include <sys/rctl_impl.h>
/*
* getrctl() system call -- executed by subject process
@@ -197,3 +197,78 @@ pr_setrctl(struct ps_prochandle *Pr, const char *rname,
}
return (rval.sys_rval1);
}
+
+/*
+ * setprojrctl() system call -- executed by subject process
+ */
+int
+pr_setprojrctl(struct ps_prochandle *Pr, const char *rname,
+ rctlblk_t *new_blk, size_t size, int rflag)
+{
+ sysret_t rval;
+ argdes_t argd[6];
+ argdes_t *adp;
+ int error;
+
+ if (Pr == NULL) /* no subject process */
+ return (setprojrctl(rname, new_blk, size, rflag));
+
+ adp = &argd[0];
+ adp->arg_value = 4; /* switch for setprojrctls in rctlsys */
+ adp->arg_object = NULL;
+ adp->arg_type = AT_BYVAL;
+ adp->arg_inout = AI_INPUT;
+ adp->arg_size = 0;
+
+ adp++;
+ adp->arg_value = 0;
+ adp->arg_object = (void *)rname;
+ adp->arg_type = AT_BYREF;
+ adp->arg_inout = AI_INPUT;
+ adp->arg_size = strlen(rname) + 1;
+
+ adp++;
+ adp->arg_value = 0; /* old_blk is not used by setprojrctls() */
+ adp->arg_object = NULL;
+ adp->arg_type = AT_BYVAL;
+ adp->arg_inout = AI_INPUT;
+ adp->arg_size = 0;
+
+
+ adp++;
+ if (new_blk == NULL) {
+ adp->arg_value = 0;
+ adp->arg_object = NULL;
+ adp->arg_type = AT_BYVAL;
+ adp->arg_inout = AI_INPUT;
+ adp->arg_size = 0;
+ } else {
+ adp->arg_value = 0;
+ adp->arg_object = new_blk;
+ adp->arg_type = AT_BYREF;
+ adp->arg_inout = AI_INPUT;
+ adp->arg_size = rctlblk_size() * size;
+ }
+
+ adp++;
+ adp->arg_value = size; /* obufsz is used by setrctls() */
+ adp->arg_object = NULL;
+ adp->arg_type = AT_BYVAL;
+ adp->arg_inout = AI_INPUT;
+ adp->arg_size = 0;
+
+ adp++;
+ adp->arg_value = rflag;
+ adp->arg_object = NULL;
+ adp->arg_type = AT_BYVAL;
+ adp->arg_inout = AI_INPUT;
+ adp->arg_size = 0;
+
+ error = Psyscall(Pr, &rval, SYS_rctlsys, 6, &argd[0]);
+
+ if (error) {
+ errno = (error > 0) ? error : ENOSYS;
+ return (-1);
+ }
+ return (rval.sys_rval1);
+}
diff --git a/usr/src/lib/libproject/common/setproject.c b/usr/src/lib/libproject/common/setproject.c
index d22878a36f..e15c719c5c 100644
--- a/usr/src/lib/libproject/common/setproject.c
+++ b/usr/src/lib/libproject/common/setproject.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,6 +36,7 @@
#include <signal.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <nss_dbdefs.h>
#include <pwd.h>
#include <pool.h>
@@ -45,6 +46,7 @@
#include <zone.h>
#include <sys/pool.h>
#include <sys/pool_impl.h>
+#include <sys/rctl_impl.h>
static void
xstrtolower(char *s)
@@ -177,7 +179,7 @@ build_rctlblk(rctlblk_t *blk, int comp_num, char *component)
#define BADSPEC 5
static int
-rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr)
+rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr, int flags)
{
int error = 0;
uint_t component = 0;
@@ -185,18 +187,68 @@ rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr)
uint_t state = 0;
char *component_head;
rctlblk_t *blk;
-
- remove_spaces(val);
- if ((blk = malloc(rctlblk_size())) == NULL) {
+ rctlblk_t *ablk;
+ int project_entity = 0;
+ int count = 0;
+ char *tmp;
+ int local_action;
+
+ /* We cannot modify a zone resource control */
+ if (strncmp(ctl_name, "zone.", strlen("zone.")) == 0) {
return (SETFAILED);
}
+ remove_spaces(val);
+
/*
- * Tear down everything with this ctl name.
+ * As we are operating in a new task, both process and task
+ * rctls are referenced by this process alone. Tear down
+ * matching process and task rctls only.
+ *
+ * blk will be the RCPRIV_SYSTEM for this resource control,
+ * populated by the last pr_setrctl().
*/
- while (pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST) != -1 &&
- rctlblk_get_privilege(blk) != RCPRIV_SYSTEM) {
- (void) pr_setrctl(Pr, ctl_name, NULL, blk, RCTL_DELETE);
+ if ((strncmp(ctl_name, "process.", strlen("process.")) == 0) ||
+ (strncmp(ctl_name, "task.", strlen("task.")) == 0)) {
+
+ if ((blk = (rctlblk_t *)malloc(rctlblk_size())) == NULL) {
+ return (SETFAILED);
+ }
+
+
+ while (pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST) != -1 &&
+ rctlblk_get_privilege(blk) != RCPRIV_SYSTEM) {
+ (void) pr_setrctl(Pr, ctl_name, NULL, blk, RCTL_DELETE);
+ }
+
+ } else if (strncmp(ctl_name, "project.", strlen("project.")) == 0) {
+ project_entity = 1;
+
+ /* Determine how many attributes we'll be setting */
+ for (tmp = val; *tmp != '\0'; tmp++) {
+ if (*tmp == '(')
+ count++;
+ }
+
+ /* Allocate sufficient memory for rctl blocks */
+ if ((count == 0) || ((ablk =
+ (rctlblk_t *)malloc(rctlblk_size() * count)) == NULL)) {
+ return (SETFAILED);
+ }
+ blk = ablk;
+
+ /*
+ * In order to set the new rctl's local_action, we'll need the
+ * current value of global_flags. We obtain global_flags by
+ * performing a pr_getrctl().
+ *
+ * The ctl_name has been verified as valid, so we have no reason
+ * to suspect that pr_getrctl() will return an error.
+ */
+ (void) pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST);
+
+ } else {
+ return (SETFAILED);
}
/*
@@ -205,11 +257,13 @@ rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr)
rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
rctlblk_set_value(blk, 0);
rctlblk_set_local_flags(blk, 0);
+
if (rctlblk_get_global_flags(blk) & RCTL_GLOBAL_DENY_ALWAYS)
- rctlblk_set_local_action(blk, RCTL_LOCAL_DENY, 0);
+ local_action = RCTL_LOCAL_DENY;
else
- rctlblk_set_local_action(blk, RCTL_LOCAL_NOACTION, 0);
+ local_action = RCTL_LOCAL_NOACTION;
+ rctlblk_set_local_action(blk, local_action, 0);
for (; ; val++) {
switch (*val) {
@@ -238,22 +292,35 @@ rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr)
state &= ~INPAREN;
component = 0;
valuecount++;
- if (pr_setrctl(Pr, ctl_name, NULL, blk,
- RCTL_INSERT) == -1)
+
+ if (project_entity &&
+ (rctlblk_get_privilege(blk) ==
+ RCPRIV_BASIC)) {
error = SETFAILED;
+ } else if (project_entity) {
+ if (valuecount > count)
+ return (SETFAILED);
+
+ if (valuecount != count)
+ blk = RCTLBLK_INC(ablk,
+ valuecount);
+ } else {
+ if (pr_setrctl(Pr, ctl_name,
+ NULL, blk, RCTL_INSERT) ==
+ -1)
+ error = SETFAILED;
+ }
/* re-initialize block */
- rctlblk_set_privilege(blk,
- RCPRIV_PRIVILEGED);
- rctlblk_set_value(blk, 0);
- rctlblk_set_local_flags(blk, 0);
- if (rctlblk_get_global_flags(blk) &
- RCTL_GLOBAL_DENY_ALWAYS)
- rctlblk_set_local_action(blk,
- RCTL_LOCAL_DENY, 0);
- else
+ if (!project_entity ||
+ (valuecount != count)) {
+ rctlblk_set_privilege(blk,
+ RCPRIV_PRIVILEGED);
+ rctlblk_set_value(blk, 0);
+ rctlblk_set_local_flags(blk, 0);
rctlblk_set_local_action(blk,
- RCTL_LOCAL_NOACTION, 0);
+ local_action, 0);
+ }
} else {
error = CLOSEBEFOREOPEN;
}
@@ -288,6 +355,12 @@ rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr)
break;
}
+ if (project_entity) {
+ blk = ablk;
+ if (pr_setprojrctl(Pr, ctl_name, blk, count, flags) == -1)
+ error = SETFAILED;
+ }
+
free(blk);
if (valuecount == 0)
@@ -465,6 +538,7 @@ setproject_proc(const char *project_name, const char *user_name, int flags,
int ret = 0;
kva_t *kv_array;
struct project local_proj; /* space to store proj if not provided */
+ const char *pool_name = NULL;
if (project_name != NULL) {
/*
@@ -508,45 +582,37 @@ setproject_proc(const char *project_name, const char *user_name, int flags,
projid = getprojid();
}
+
+ if ((kv_array = _str2kva(proj->pj_attr, KV_ASSIGN,
+ KV_DELIMITER)) != NULL) {
+ for (i = 0; i < kv_array->length; i++) {
+ if (strcmp(kv_array->data[i].key,
+ "project.pool") == 0) {
+ pool_name = kv_array->data[i].value;
+ }
+ if (strcmp(kv_array->data[i].key, "task.final") == 0) {
+ flags |= TASK_FINAL;
+ }
+ }
+ }
+
/*
- * Only bind to a pool if pools are configured.
+ * Bind process to a pool only if pools are configured
*/
if (pools_enabled() == 1) {
- const char *pool_name = NULL;
char *old_pool_name;
- int taskflags = flags;
/*
* Attempt to bind to pool before calling
* settaskid().
*/
- if ((kv_array = _str2kva(proj->pj_attr, KV_ASSIGN,
- KV_DELIMITER)) != NULL) {
- for (i = 0; i < kv_array->length; i++) {
- if (strcmp(kv_array->data[i].key,
- "project.pool") == 0) {
- pool_name = kv_array->data[i].value;
- break;
- }
- if (strcmp(kv_array->data[i].key,
- "task.final") == 0) {
- taskflags |= TASK_FINAL;
- }
- }
- }
-
old_pool_name = pool_get_binding(pid);
-
- /*
- * If parent is not bound to the default pool, then we want
- * to preserve same binding as parent.
- */
- if (pool_name != NULL && bind_to_pool(pool_name, pid, 0) != 0) {
+ if (bind_to_pool(pool_name, pid, 0) != 0) {
if (old_pool_name)
free(old_pool_name);
_kva_free(kv_array);
return (SETPROJ_ERR_POOL);
}
- if (pr_settaskid(Pr, projid, taskflags) == -1) {
+ if (pr_settaskid(Pr, projid, flags & TASK_MASK) == -1) {
int saved_errno = errno;
/*
@@ -568,9 +634,10 @@ setproject_proc(const char *project_name, const char *user_name, int flags,
/*
* Pools are not configured, so simply create new task.
*/
- if (pr_settaskid(Pr, projid, flags) == -1)
+ if (pr_settaskid(Pr, projid, flags & TASK_MASK) == -1) {
+ _kva_free(kv_array);
return (SETPROJ_ERR_TASK);
- kv_array = _str2kva(proj->pj_attr, KV_ASSIGN, KV_DELIMITER);
+ }
}
if (project_name == NULL) {
@@ -612,7 +679,7 @@ setproject_proc(const char *project_name, const char *user_name, int flags,
}
ret = rctl_set(kv_array->data[i].key,
- kv_array->data[i].value, Pr);
+ kv_array->data[i].value, Pr, flags & TASK_PROJ_MASK);
if (ret && unknown == 0) {
/*