patch-2.1.100 linux/fs/exec.c
Next file: linux/fs/ext2/acl.c
Previous file: linux/fs/dquot.c
Back to the patch index
Back to the overall index
- Lines: 111
- Date:
Wed May 6 11:01:46 1998
- Orig file:
v2.1.99/linux/fs/exec.c
- Orig date:
Mon Apr 6 17:41:00 1998
diff -u --recursive --new-file v2.1.99/linux/fs/exec.c linux/fs/exec.c
@@ -419,6 +419,7 @@
retval = new_page_tables(current);
if (retval)
goto fail_restore;
+ activate_context(current);
up(&mm->mmap_sem);
mmput(old_mm);
return 0;
@@ -564,7 +565,7 @@
int prepare_binprm(struct linux_binprm *bprm)
{
int mode;
- int retval,id_change;
+ int retval,id_change,cap_raised;
struct inode * inode = bprm->dentry->d_inode;
mode = inode->i_mode;
@@ -584,7 +585,7 @@
bprm->e_uid = current->euid;
bprm->e_gid = current->egid;
- id_change = 0;
+ id_change = cap_raised = 0;
/* Set-uid? */
if (mode & S_ISUID) {
@@ -630,21 +631,25 @@
cap_set_full(bprm->cap_effective);
}
- /* We use a conservative definition of suid for capabilities.
- * The process is suid if the permitted set is not a subset of
- * the current permitted set after the exec call.
- * new permitted set = forced | (allowed & inherited)
- * pP' = fP | (fI & pI)
- */
-
- if ((bprm->cap_permitted.cap |
- (current->cap_inheritable.cap &
- bprm->cap_inheritable.cap)) &
- ~current->cap_permitted.cap) {
- id_change = 1;
+ /* Only if pP' is _not_ a subset of pP, do we consider there
+ * has been a capability related "change of capability". In
+ * such cases, we need to check that the elevation of
+ * privilege does not go against other system constraints.
+ * The new Permitted set is defined below -- see (***). */
+ {
+ kernel_cap_t working =
+ cap_combine(bprm->cap_permitted,
+ cap_intersect(bprm->cap_inheritable,
+ current->cap_inheritable));
+ if (!cap_issubset(working, current->cap_permitted)) {
+ cap_raised = 1;
+ }
}
- if (id_change) {
+
+
+
+ if (id_change || cap_raised) {
/* We can't suid-execute if we're sharing parts of the executable */
/* or if we're being traced (or if suid execs are not allowed) */
/* (current->mm->count > 1 is ok, as we'll get a new mm anyway) */
@@ -653,8 +658,10 @@
|| (current->fs->count > 1)
|| (atomic_read(¤t->sig->count) > 1)
|| (current->files->count > 1)) {
- if (!suser())
- return -EPERM;
+ if (id_change && !capable(CAP_SETUID))
+ return -EPERM;
+ if (cap_raised && !capable(CAP_SETPCAP))
+ return -EPERM;
}
}
@@ -669,7 +676,7 @@
* The formula used for evolving capabilities is:
*
* pI' = pI
- * pP' = fP | (fI & pI)
+ * (***) pP' = fP | (fI & pI)
* pE' = pP' & fE [NB. fE is 0 or ~0]
*
* I=Inheritable, P=Permitted, E=Effective // p=process, f=file
@@ -678,11 +685,18 @@
void compute_creds(struct linux_binprm *bprm)
{
- int new_permitted = bprm->cap_permitted.cap |
- (bprm->cap_inheritable.cap & current->cap_inheritable.cap);
-
- current->cap_permitted.cap = new_permitted;
- current->cap_effective.cap = new_permitted & bprm->cap_effective.cap;
+ /* For init, we want to retain the capabilities set
+ * in the init_task struct. Thus we skip the usual
+ * capability rules */
+ if (current->pid != 1) {
+ int new_permitted = bprm->cap_permitted.cap |
+ (bprm->cap_inheritable.cap &
+ current->cap_inheritable.cap);
+
+ current->cap_permitted.cap = new_permitted;
+ current->cap_effective.cap = new_permitted &
+ bprm->cap_effective.cap;
+ }
/* AUD: Audit candidate if current->cap_effective is set */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov