Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 120728
b: refs/heads/master
c: a6f76f2
h: refs/heads/master
v: v3
  • Loading branch information
David Howells authored and James Morris committed Nov 13, 2008
1 parent f78b91d commit e1f1598
Show file tree
Hide file tree
Showing 24 changed files with 430 additions and 516 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d84f4f992cbd76e8f39c488cf0c5d123843923b1
refs/heads/master: a6f76f23d297f70e2a6b3ec607f7aeeea9e37e8d
2 changes: 1 addition & 1 deletion trunk/arch/x86/ia32/ia32_aout.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
current->mm->cached_hole_size = 0;

current->mm->mmap = NULL;
compute_creds(bprm);
install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;

if (N_MAGIC(ex) == OMAGIC) {
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/binfmt_aout.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->free_area_cache = current->mm->mmap_base;
current->mm->cached_hole_size = 0;

compute_creds(bprm);
install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
#ifdef __sparc__
if (N_MAGIC(ex) == NMAGIC) {
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
}
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */

compute_creds(bprm);
install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
retval = create_elf_tables(bprm, &loc->elf_ex,
load_addr, interp_load_addr);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/binfmt_elf_fdpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
current->mm->start_stack = current->mm->start_brk + stack_size;
#endif

compute_creds(bprm);
install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
if (create_elf_fdpic_tables(bprm, current->mm,
&exec_params, &interp_params) < 0)
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/binfmt_flat.c
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
(libinfo.lib_list[j].loaded)?
libinfo.lib_list[j].start_data:UNLOADED_LIB;

compute_creds(bprm);
install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;

set_binfmt(&flat_format);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/binfmt_som.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
kfree(hpuxhdr);

set_binfmt(&som_format);
compute_creds(bprm);
install_exec_creds(bprm);
setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);

create_som_tables(bprm);
Expand Down
42 changes: 24 additions & 18 deletions trunk/fs/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1393,10 +1393,20 @@ int compat_do_execve(char * filename,
if (!bprm)
goto out_ret;

retval = mutex_lock_interruptible(&current->cred_exec_mutex);
if (retval < 0)
goto out_free;

retval = -ENOMEM;
bprm->cred = prepare_exec_creds();
if (!bprm->cred)
goto out_unlock;
check_unsafe_exec(bprm);

file = open_exec(filename);
retval = PTR_ERR(file);
if (IS_ERR(file))
goto out_kfree;
goto out_unlock;

sched_exec();

Expand All @@ -1410,14 +1420,10 @@ int compat_do_execve(char * filename,

bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
if ((retval = bprm->argc) < 0)
goto out_mm;
goto out;

bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
if ((retval = bprm->envc) < 0)
goto out_mm;

retval = security_bprm_alloc(bprm);
if (retval)
goto out;

retval = prepare_binprm(bprm);
Expand All @@ -1438,19 +1444,16 @@ int compat_do_execve(char * filename,
goto out;

retval = search_binary_handler(bprm, regs);
if (retval >= 0) {
/* execve success */
security_bprm_free(bprm);
acct_update_integrals(current);
free_bprm(bprm);
return retval;
}
if (retval < 0)
goto out;

out:
if (bprm->security)
security_bprm_free(bprm);
/* execve succeeded */
mutex_unlock(&current->cred_exec_mutex);
acct_update_integrals(current);
free_bprm(bprm);
return retval;

out_mm:
out:
if (bprm->mm)
mmput(bprm->mm);

Expand All @@ -1460,7 +1463,10 @@ int compat_do_execve(char * filename,
fput(bprm->file);
}

out_kfree:
out_unlock:
mutex_unlock(&current->cred_exec_mutex);

out_free:
free_bprm(bprm);

out_ret:
Expand Down
149 changes: 86 additions & 63 deletions trunk/fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/tlb.h>
#include "internal.h"

#ifdef __alpha__
/* for /sbin/loader handling in search_binary_handler() */
Expand Down Expand Up @@ -1007,15 +1008,17 @@ int flush_old_exec(struct linux_binprm * bprm)
*/
current->mm->task_size = TASK_SIZE;

if (bprm->e_uid != current_euid() ||
bprm->e_gid != current_egid()) {
set_dumpable(current->mm, suid_dumpable);
/* install the new credentials */
if (bprm->cred->uid != current_euid() ||
bprm->cred->gid != current_egid()) {
current->pdeath_signal = 0;
} else if (file_permission(bprm->file, MAY_READ) ||
(bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) {
set_dumpable(current->mm, suid_dumpable);
}

current->personality &= ~bprm->per_clear;

/* An exec changes our domain. We are no longer part of the thread
group */

Expand All @@ -1032,28 +1035,66 @@ int flush_old_exec(struct linux_binprm * bprm)

EXPORT_SYMBOL(flush_old_exec);

/*
* install the new credentials for this executable
*/
void install_exec_creds(struct linux_binprm *bprm)
{
security_bprm_committing_creds(bprm);

commit_creds(bprm->cred);
bprm->cred = NULL;

/* cred_exec_mutex must be held at least to this point to prevent
* ptrace_attach() from altering our determination of the task's
* credentials; any time after this it may be unlocked */

security_bprm_committed_creds(bprm);
}
EXPORT_SYMBOL(install_exec_creds);

/*
* determine how safe it is to execute the proposed program
* - the caller must hold current->cred_exec_mutex to protect against
* PTRACE_ATTACH
*/
void check_unsafe_exec(struct linux_binprm *bprm)
{
struct task_struct *p = current;

bprm->unsafe = tracehook_unsafe_exec(p);

if (atomic_read(&p->fs->count) > 1 ||
atomic_read(&p->files->count) > 1 ||
atomic_read(&p->sighand->count) > 1)
bprm->unsafe |= LSM_UNSAFE_SHARE;
}

/*
* Fill the binprm structure from the inode.
* Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
*
* This may be called multiple times for binary chains (scripts for example).
*/
int prepare_binprm(struct linux_binprm *bprm)
{
int mode;
umode_t mode;
struct inode * inode = bprm->file->f_path.dentry->d_inode;
int retval;

mode = inode->i_mode;
if (bprm->file->f_op == NULL)
return -EACCES;

bprm->e_uid = current_euid();
bprm->e_gid = current_egid();
/* clear any previous set[ug]id data from a previous binary */
bprm->cred->euid = current_euid();
bprm->cred->egid = current_egid();

if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
/* Set-uid? */
if (mode & S_ISUID) {
current->personality &= ~PER_CLEAR_ON_SETID;
bprm->e_uid = inode->i_uid;
bprm->per_clear |= PER_CLEAR_ON_SETID;
bprm->cred->euid = inode->i_uid;
}

/* Set-gid? */
Expand All @@ -1063,50 +1104,23 @@ int prepare_binprm(struct linux_binprm *bprm)
* executable.
*/
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
current->personality &= ~PER_CLEAR_ON_SETID;
bprm->e_gid = inode->i_gid;
bprm->per_clear |= PER_CLEAR_ON_SETID;
bprm->cred->egid = inode->i_gid;
}
}

/* fill in binprm security blob */
retval = security_bprm_set(bprm);
retval = security_bprm_set_creds(bprm);
if (retval)
return retval;
bprm->cred_prepared = 1;

memset(bprm->buf,0,BINPRM_BUF_SIZE);
return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
memset(bprm->buf, 0, BINPRM_BUF_SIZE);
return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
}

EXPORT_SYMBOL(prepare_binprm);

static int unsafe_exec(struct task_struct *p)
{
int unsafe = tracehook_unsafe_exec(p);

if (atomic_read(&p->fs->count) > 1 ||
atomic_read(&p->files->count) > 1 ||
atomic_read(&p->sighand->count) > 1)
unsafe |= LSM_UNSAFE_SHARE;

return unsafe;
}

void compute_creds(struct linux_binprm *bprm)
{
int unsafe;

if (bprm->e_uid != current_uid())
current->pdeath_signal = 0;
exec_keys(current);

task_lock(current);
unsafe = unsafe_exec(current);
security_bprm_apply_creds(bprm, unsafe);
task_unlock(current);
security_bprm_post_apply_creds(bprm);
}
EXPORT_SYMBOL(compute_creds);

/*
* Arguments are '\0' separated strings found at the location bprm->p
* points to; chop off the first by relocating brpm->p to right after
Expand Down Expand Up @@ -1259,6 +1273,8 @@ EXPORT_SYMBOL(search_binary_handler);
void free_bprm(struct linux_binprm *bprm)
{
free_arg_pages(bprm);
if (bprm->cred)
abort_creds(bprm->cred);
kfree(bprm);
}

Expand All @@ -1284,10 +1300,20 @@ int do_execve(char * filename,
if (!bprm)
goto out_files;

retval = mutex_lock_interruptible(&current->cred_exec_mutex);
if (retval < 0)
goto out_free;

retval = -ENOMEM;
bprm->cred = prepare_exec_creds();
if (!bprm->cred)
goto out_unlock;
check_unsafe_exec(bprm);

file = open_exec(filename);
retval = PTR_ERR(file);
if (IS_ERR(file))
goto out_kfree;
goto out_unlock;

sched_exec();

Expand All @@ -1301,14 +1327,10 @@ int do_execve(char * filename,

bprm->argc = count(argv, MAX_ARG_STRINGS);
if ((retval = bprm->argc) < 0)
goto out_mm;
goto out;

bprm->envc = count(envp, MAX_ARG_STRINGS);
if ((retval = bprm->envc) < 0)
goto out_mm;

retval = security_bprm_alloc(bprm);
if (retval)
goto out;

retval = prepare_binprm(bprm);
Expand All @@ -1330,21 +1352,18 @@ int do_execve(char * filename,

current->flags &= ~PF_KTHREAD;
retval = search_binary_handler(bprm,regs);
if (retval >= 0) {
/* execve success */
security_bprm_free(bprm);
acct_update_integrals(current);
free_bprm(bprm);
if (displaced)
put_files_struct(displaced);
return retval;
}
if (retval < 0)
goto out;

out:
if (bprm->security)
security_bprm_free(bprm);
/* execve succeeded */
mutex_unlock(&current->cred_exec_mutex);
acct_update_integrals(current);
free_bprm(bprm);
if (displaced)
put_files_struct(displaced);
return retval;

out_mm:
out:
if (bprm->mm)
mmput (bprm->mm);

Expand All @@ -1353,7 +1372,11 @@ int do_execve(char * filename,
allow_write_access(bprm->file);
fput(bprm->file);
}
out_kfree:

out_unlock:
mutex_unlock(&current->cred_exec_mutex);

out_free:
free_bprm(bprm);

out_files:
Expand Down
Loading

0 comments on commit e1f1598

Please sign in to comment.