patch-2.4.0-prerelease linux/fs/exec.c
Next file: linux/fs/ext2/Makefile
Previous file: linux/fs/efs/symlink.c
Back to the patch index
Back to the overall index
- Lines: 202
- Date:
Sun Dec 31 11:06:00 2000
- Orig file:
v2.4.0-test12/linux/fs/exec.c
- Orig date:
Mon Dec 11 17:59:45 2000
diff -u --recursive --new-file v2.4.0-test12/linux/fs/exec.c linux/fs/exec.c
@@ -223,8 +223,6 @@
memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len);
}
err = copy_from_user(kaddr + offset, str, bytes_to_copy);
- flush_dcache_page(page);
- flush_page_to_ram(page);
kunmap(page);
if (err)
@@ -281,6 +279,7 @@
__free_page(page);
return;
}
+ flush_dcache_page(page);
flush_page_to_ram(page);
set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, PAGE_COPY))));
/* no need for flush_tlb */
@@ -314,9 +313,7 @@
mpnt->vm_pgoff = 0;
mpnt->vm_file = NULL;
mpnt->vm_private_data = (void *) 0;
- spin_lock(¤t->mm->page_table_lock);
insert_vm_struct(current->mm, mpnt);
- spin_unlock(¤t->mm->page_table_lock);
current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
}
@@ -597,7 +594,6 @@
int prepare_binprm(struct linux_binprm *bprm)
{
int mode;
- int id_change,cap_raised;
struct inode * inode = bprm->file->f_dentry->d_inode;
mode = inode->i_mode;
@@ -609,25 +605,20 @@
bprm->e_uid = current->euid;
bprm->e_gid = current->egid;
- id_change = cap_raised = 0;
- /* Set-uid? */
- if (mode & S_ISUID) {
- bprm->e_uid = inode->i_uid;
- if (bprm->e_uid != current->euid)
- id_change = 1;
- }
-
- /* Set-gid? */
- /*
- * If setgid is set but no group execute bit then this
- * is a candidate for mandatory locking, not a setgid
- * executable.
- */
- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
- bprm->e_gid = inode->i_gid;
- if (!in_group_p(bprm->e_gid))
- id_change = 1;
+ if(!IS_NOSUID(inode)) {
+ /* Set-uid? */
+ if (mode & S_ISUID)
+ bprm->e_uid = inode->i_uid;
+
+ /* Set-gid? */
+ /*
+ * If setgid is set but no group execute bit then this
+ * is a candidate for mandatory locking, not a setgid
+ * executable.
+ */
+ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
+ bprm->e_gid = inode->i_gid;
}
/* We don't have VFS support for capabilities yet */
@@ -652,39 +643,6 @@
cap_set_full(bprm->cap_effective);
}
- /* 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 permitted, working;
-
- permitted = cap_intersect(bprm->cap_permitted, cap_bset);
- working = cap_intersect(bprm->cap_inheritable,
- current->cap_inheritable);
- working = cap_combine(permitted, working);
- if (!cap_issubset(working, current->cap_permitted)) {
- cap_raised = 1;
- }
- }
-
- 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->mm_users > 1 is ok, as we'll get a new mm anyway) */
- if (IS_NOSUID(inode)
- || must_not_trace_exec(current)
- || (atomic_read(¤t->fs->count) > 1)
- || (atomic_read(¤t->sig->count) > 1)
- || (atomic_read(¤t->files->count) > 1)) {
- if (id_change && !capable(CAP_SETUID))
- return -EPERM;
- if (cap_raised && !capable(CAP_SETPCAP))
- return -EPERM;
- }
- }
-
memset(bprm->buf,0,BINPRM_BUF_SIZE);
return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
}
@@ -701,17 +659,41 @@
*
* I=Inheritable, P=Permitted, E=Effective // p=process, f=file
* ' indicates post-exec(), and X is the global 'cap_bset'.
+ *
*/
void compute_creds(struct linux_binprm *bprm)
{
kernel_cap_t new_permitted, working;
+ int do_unlock = 0;
new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);
working = cap_intersect(bprm->cap_inheritable,
current->cap_inheritable);
new_permitted = cap_combine(new_permitted, working);
+ if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
+ !cap_issubset(new_permitted, current->cap_permitted)) {
+ current->dumpable = 0;
+
+ lock_kernel();
+ if (must_not_trace_exec(current)
+ || atomic_read(¤t->fs->count) > 1
+ || atomic_read(¤t->files->count) > 1
+ || atomic_read(¤t->sig->count) > 1) {
+ if(!capable(CAP_SETUID)) {
+ bprm->e_uid = current->uid;
+ bprm->e_gid = current->gid;
+ }
+ if(!capable(CAP_SETPCAP)) {
+ new_permitted = cap_intersect(new_permitted,
+ current->cap_permitted);
+ }
+ }
+ do_unlock = 1;
+ }
+
+
/* For init, we want to retain the capabilities set
* in the init_task struct. Thus we skip the usual
* capability rules */
@@ -725,10 +707,9 @@
current->suid = current->euid = current->fsuid = bprm->e_uid;
current->sgid = current->egid = current->fsgid = bprm->e_gid;
- if (current->euid != current->uid || current->egid != current->gid ||
- !cap_issubset(new_permitted, current->cap_permitted))
- current->dumpable = 0;
+ if(do_unlock)
+ unlock_kernel();
current->keep_capabilities = 0;
}
@@ -768,29 +749,26 @@
/* handle /sbin/loader.. */
{
struct exec * eh = (struct exec *) bprm->buf;
- struct linux_binprm bprm_loader;
if (!bprm->loader && eh->fh.f_magic == 0x183 &&
(eh->fh.f_flags & 0x3000) == 0x3000)
{
- int i;
char * dynloader[] = { "/sbin/loader" };
struct file * file;
+ unsigned long loader;
allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
- bprm_loader.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
- for (i = 0 ; i < MAX_ARG_PAGES ; i++) /* clear page-table */
- bprm_loader.page[i] = NULL;
+ loader = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
file = open_exec(dynloader[0]);
retval = PTR_ERR(file);
if (IS_ERR(file))
return retval;
bprm->file = file;
- bprm->loader = bprm_loader.p;
+ bprm->loader = loader;
retval = prepare_binprm(bprm);
if (retval<0)
return retval;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)