Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 120727
b: refs/heads/master
c: d84f4f9
h: refs/heads/master
i:
  120725: 1643658
  120723: 7958ad5
  120719: 2c8d1e2
v: v3
  • Loading branch information
David Howells authored and James Morris committed Nov 13, 2008
1 parent fc0d400 commit f78b91d
Show file tree
Hide file tree
Showing 42 changed files with 1,604 additions and 1,240 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: 745ca2475a6ac596e3d8d37c2759c0fbe2586227
refs/heads/master: d84f4f992cbd76e8f39c488cf0c5d123843923b1
31 changes: 21 additions & 10 deletions trunk/fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1007,13 +1007,12 @@ 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()) {
suid_keys(current);
if (bprm->e_uid != current_euid() ||
bprm->e_gid != current_egid()) {
set_dumpable(current->mm, suid_dumpable);
current->pdeath_signal = 0;
} else if (file_permission(bprm->file, MAY_READ) ||
(bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
suid_keys(current);
set_dumpable(current->mm, suid_dumpable);
}

Expand Down Expand Up @@ -1096,10 +1095,8 @@ void compute_creds(struct linux_binprm *bprm)
{
int unsafe;

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

task_lock(current);
Expand Down Expand Up @@ -1709,8 +1706,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
struct linux_binfmt * binfmt;
struct inode * inode;
struct file * file;
const struct cred *old_cred;
struct cred *cred;
int retval = 0;
int fsuid = current_fsuid();
int flag = 0;
int ispipe = 0;
unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
Expand All @@ -1723,12 +1721,20 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
binfmt = current->binfmt;
if (!binfmt || !binfmt->core_dump)
goto fail;

cred = prepare_creds();
if (!cred) {
retval = -ENOMEM;
goto fail;
}

down_write(&mm->mmap_sem);
/*
* If another thread got here first, or we are not dumpable, bail out.
*/
if (mm->core_state || !get_dumpable(mm)) {
up_write(&mm->mmap_sem);
put_cred(cred);
goto fail;
}

Expand All @@ -1739,12 +1745,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
*/
if (get_dumpable(mm) == 2) { /* Setuid core dump mode */
flag = O_EXCL; /* Stop rewrite attacks */
current->cred->fsuid = 0; /* Dump root private */
cred->fsuid = 0; /* Dump root private */
}

retval = coredump_wait(exit_code, &core_state);
if (retval < 0)
if (retval < 0) {
put_cred(cred);
goto fail;
}

old_cred = override_creds(cred);

/*
* Clear any false indication of pending signals that might
Expand Down Expand Up @@ -1835,7 +1845,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
if (helper_argv)
argv_free(helper_argv);

current->cred->fsuid = fsuid;
revert_creds(old_cred);
put_cred(cred);
coredump_finish(mm);
fail:
return retval;
Expand Down
92 changes: 52 additions & 40 deletions trunk/fs/nfsd/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,55 +27,67 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)

int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
{
struct cred *act_as = current->cred ;
struct svc_cred cred = rqstp->rq_cred;
struct group_info *rqgi;
struct group_info *gi;
struct cred *new;
int i;
int flags = nfsexp_flags(rqstp, exp);
int ret;

new = prepare_creds();
if (!new)
return -ENOMEM;

new->fsuid = rqstp->rq_cred.cr_uid;
new->fsgid = rqstp->rq_cred.cr_gid;

rqgi = rqstp->rq_cred.cr_group_info;

if (flags & NFSEXP_ALLSQUASH) {
cred.cr_uid = exp->ex_anon_uid;
cred.cr_gid = exp->ex_anon_gid;
cred.cr_group_info = groups_alloc(0);
new->fsuid = exp->ex_anon_uid;
new->fsgid = exp->ex_anon_gid;
gi = groups_alloc(0);
} else if (flags & NFSEXP_ROOTSQUASH) {
struct group_info *gi;
if (!cred.cr_uid)
cred.cr_uid = exp->ex_anon_uid;
if (!cred.cr_gid)
cred.cr_gid = exp->ex_anon_gid;
gi = groups_alloc(cred.cr_group_info->ngroups);
if (gi)
for (i = 0; i < cred.cr_group_info->ngroups; i++) {
if (!GROUP_AT(cred.cr_group_info, i))
GROUP_AT(gi, i) = exp->ex_anon_gid;
else
GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i);
}
cred.cr_group_info = gi;
} else
get_group_info(cred.cr_group_info);

if (cred.cr_uid != (uid_t) -1)
act_as->fsuid = cred.cr_uid;
else
act_as->fsuid = exp->ex_anon_uid;
if (cred.cr_gid != (gid_t) -1)
act_as->fsgid = cred.cr_gid;
else
act_as->fsgid = exp->ex_anon_gid;
if (!new->fsuid)
new->fsuid = exp->ex_anon_uid;
if (!new->fsgid)
new->fsgid = exp->ex_anon_gid;

if (!cred.cr_group_info)
return -ENOMEM;
ret = set_groups(act_as, cred.cr_group_info);
put_group_info(cred.cr_group_info);
if ((cred.cr_uid)) {
act_as->cap_effective =
cap_drop_nfsd_set(act_as->cap_effective);
gi = groups_alloc(rqgi->ngroups);
if (!gi)
goto oom;

for (i = 0; i < rqgi->ngroups; i++) {
if (!GROUP_AT(rqgi, i))
GROUP_AT(gi, i) = exp->ex_anon_gid;
else
GROUP_AT(gi, i) = GROUP_AT(rqgi, i);
}
} else {
act_as->cap_effective =
cap_raise_nfsd_set(act_as->cap_effective,
act_as->cap_permitted);
gi = get_group_info(rqgi);
}

if (new->fsuid == (uid_t) -1)
new->fsuid = exp->ex_anon_uid;
if (new->fsgid == (gid_t) -1)
new->fsgid = exp->ex_anon_gid;

ret = set_groups(new, gi);
put_group_info(gi);
if (!ret)
goto error;

if (new->uid)
new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
else
new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
new->cap_permitted);
return commit_creds(new);

oom:
ret = -ENOMEM;
error:
abort_creds(new);
return ret;
}

68 changes: 42 additions & 26 deletions trunk/fs/nfsd/nfs4recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,26 @@
static struct path rec_dir;
static int rec_dir_init = 0;

static void
nfs4_save_user(uid_t *saveuid, gid_t *savegid)
static int
nfs4_save_creds(const struct cred **original_creds)
{
*saveuid = current->cred->fsuid;
*savegid = current->cred->fsgid;
current->cred->fsuid = 0;
current->cred->fsgid = 0;
struct cred *new;

new = prepare_creds();
if (!new)
return -ENOMEM;

new->fsuid = 0;
new->fsgid = 0;
*original_creds = override_creds(new);
put_cred(new);
return 0;
}

static void
nfs4_reset_user(uid_t saveuid, gid_t savegid)
nfs4_reset_creds(const struct cred *original)
{
current->cred->fsuid = saveuid;
current->cred->fsgid = savegid;
revert_creds(original);
}

static void
Expand Down Expand Up @@ -129,18 +135,19 @@ nfsd4_sync_rec_dir(void)
int
nfsd4_create_clid_dir(struct nfs4_client *clp)
{
const struct cred *original_cred;
char *dname = clp->cl_recdir;
struct dentry *dentry;
uid_t uid;
gid_t gid;
int status;

dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);

if (!rec_dir_init || clp->cl_firststate)
return 0;

nfs4_save_user(&uid, &gid);
status = nfs4_save_creds(&original_cred);
if (status < 0)
return status;

/* lock the parent */
mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
Expand Down Expand Up @@ -168,7 +175,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
clp->cl_firststate = 1;
nfsd4_sync_rec_dir();
}
nfs4_reset_user(uid, gid);
nfs4_reset_creds(original_cred);
dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
return status;
}
Expand Down Expand Up @@ -211,20 +218,21 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
static int
nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
{
const struct cred *original_cred;
struct file *filp;
struct dentry_list_arg dla = {
.parent = dir,
};
struct list_head *dentries = &dla.dentries;
struct dentry_list *child;
uid_t uid;
gid_t gid;
int status;

if (!rec_dir_init)
return 0;

nfs4_save_user(&uid, &gid);
status = nfs4_save_creds(&original_cred);
if (status < 0)
return status;

filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY,
current_cred());
Expand All @@ -250,7 +258,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
dput(child->dentry);
kfree(child);
}
nfs4_reset_user(uid, gid);
nfs4_reset_creds(original_cred);
return status;
}

Expand Down Expand Up @@ -312,8 +320,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
void
nfsd4_remove_clid_dir(struct nfs4_client *clp)
{
uid_t uid;
gid_t gid;
const struct cred *original_cred;
int status;

if (!rec_dir_init || !clp->cl_firststate)
Expand All @@ -323,9 +330,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
if (status)
goto out;
clp->cl_firststate = 0;
nfs4_save_user(&uid, &gid);

status = nfs4_save_creds(&original_cred);
if (status < 0)
goto out;

status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
nfs4_reset_user(uid, gid);
nfs4_reset_creds(original_cred);
if (status == 0)
nfsd4_sync_rec_dir();
mnt_drop_write(rec_dir.mnt);
Expand Down Expand Up @@ -402,16 +413,21 @@ nfsd4_recdir_load(void) {
void
nfsd4_init_recdir(char *rec_dirname)
{
uid_t uid = 0;
gid_t gid = 0;
int status;
const struct cred *original_cred;
int status;

printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
rec_dirname);

BUG_ON(rec_dir_init);

nfs4_save_user(&uid, &gid);
status = nfs4_save_creds(&original_cred);
if (status < 0) {
printk("NFSD: Unable to change credentials to find recovery"
" directory: error %d\n",
status);
return;
}

status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
&rec_dir);
Expand All @@ -421,7 +437,7 @@ nfsd4_init_recdir(char *rec_dirname)

if (!status)
rec_dir_init = 1;
nfs4_reset_user(uid, gid);
nfs4_reset_creds(original_cred);
}

void
Expand Down
11 changes: 8 additions & 3 deletions trunk/fs/nfsd/nfsfh.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
* access control settings being in effect, we cannot
* fix that case easily.
*/
current->cred->cap_effective =
cap_raise_nfsd_set(current->cred->cap_effective,
current->cred->cap_permitted);
struct cred *new = prepare_creds();
if (!new)
return nfserrno(-ENOMEM);
new->cap_effective =
cap_raise_nfsd_set(new->cap_effective,
new->cap_permitted);
put_cred(override_creds(new));
put_cred(new);
} else {
error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
Expand Down
Loading

0 comments on commit f78b91d

Please sign in to comment.