summaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-10 17:17:53 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-10 17:17:53 +0000
commitb2ad5f821b1381492d792ca10b1eb7a107b48f14 (patch)
tree954a648692e7da983db1d2470953705f6a729264 /fs/exec.c
parentc9c06167e7933d93a6e396174c68abf242294abb (diff)
Merge with Linux 2.4.0-prerelease. Big Makefile rewrite, test your
Makefiles.
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c108
1 files changed, 43 insertions, 65 deletions
diff --git a/fs/exec.c b/fs/exec.c
index f04fab7e3..36f3a8c6e 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -223,8 +223,6 @@ int copy_strings(int argc,char ** argv, struct linux_binprm *bprm)
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 @@ void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long a
__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 @@ int setup_arg_pages(struct linux_binprm *bprm)
mpnt->vm_pgoff = 0;
mpnt->vm_file = NULL;
mpnt->vm_private_data = (void *) 0;
- spin_lock(&current->mm->page_table_lock);
insert_vm_struct(current->mm, mpnt);
- spin_unlock(&current->mm->page_table_lock);
current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
}
@@ -597,7 +594,6 @@ static inline int must_not_trace_exec(struct task_struct * p)
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 @@ int prepare_binprm(struct linux_binprm *bprm)
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 @@ int prepare_binprm(struct linux_binprm *bprm)
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(&current->fs->count) > 1)
- || (atomic_read(&current->sig->count) > 1)
- || (atomic_read(&current->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 @@ int prepare_binprm(struct linux_binprm *bprm)
*
* 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(&current->fs->count) > 1
+ || atomic_read(&current->files->count) > 1
+ || atomic_read(&current->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 @@ void compute_creds(struct linux_binprm *bprm)
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 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
/* 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;