Messages in this thread Patch in this message | | | Subject | [PATCH] (That Works) Security patch for fs/nfsd | Date | Wed, 11 Nov 1998 14:54:12 -0800 | From | "G. Allen Morris III" <> |
| |
>>> Linus Torvalds said: > Note that I wasn't talking about your fixes - I was really pissed off > becasue the last set of patches I tried to apply from this list (from > Morris) didn't even pass through "patch" without patch complaining. And it > wasn't the first time that had happened. When somethng like that keeps on > happening, I just keep wondering..
Please accept my apologies! Below is a patch that will go through `patch'.
>>>"G. Allen Morris III" said: Patch to linux 2.1.127 for fs/nfsd/
The sub-mount patch was overly restrictive. This one, I hope, acts more like the local filesystems.
1. [SECURITY] It seems that knfsd does not test permissions correctly for SETATTR. I think this has been fixed by adding: err = inode_change_ok(inode, iap);
2. On root_squashed exports root could not mount subdirectories/files that where in directories where `nobody' didn't have EXECUTE permition. This was true even if other users would be able to access that directory.
You can now get access through directories that are EXECUTABLE by anyone other than root (or if you can become root).
3. All file capabilities are reset now unless access is by root.
Patch is also available at: http://csua.berkeley.edu/~gam3/knfsd/
----------------------- nfsd-2.1.127-5.patch ------------------------------- Index: linux/fs/nfsd/auth.c diff -u linux/fs/nfsd/auth.c:1.2 linux/fs/nfsd/auth.c:1.2.2.1 --- linux/fs/nfsd/auth.c:1.2 Sat Nov 7 16:43:38 1998 +++ linux/fs/nfsd/auth.c Tue Nov 10 10:31:46 1998 @@ -50,11 +50,10 @@ current->ngroups = i; if ((cred->cr_uid)) { - cap_lower(current->cap_effective, CAP_DAC_OVERRIDE); - cap_lower(current->cap_effective, CAP_DAC_READ_SEARCH); + cap_t(current->cap_effective) &= ~CAP_FS_MASK; } else { - cap_raise(current->cap_effective, CAP_DAC_OVERRIDE); - cap_raise(current->cap_effective, CAP_DAC_READ_SEARCH); + cap_t(current->cap_effective) |= (CAP_FS_MASK & + current->cap_permitted); } rqstp->rq_userset = 1; Index: linux/fs/nfsd/nfsfh.c diff -u linux/fs/nfsd/nfsfh.c:1.3 linux/fs/nfsd/nfsfh.c:1.3.2.4 --- linux/fs/nfsd/nfsfh.c:1.3 Sat Nov 7 16:43:38 1998 +++ linux/fs/nfsd/nfsfh.c Tue Nov 10 10:31:46 1998 @@ -1093,47 +1093,48 @@ /* * Security: Check that the export is valid for dentry <gam3@acm.org> */ + error = 0; if (fh->fh_dev != fh->fh_xdev) { printk("fh_verify: Security: export on other device" " (%d, %d).\n", fh->fh_dev, fh->fh_xdev); - goto out; + error = nfserr_stale; } else if (exp->ex_dentry != dentry) { struct dentry *tdentry = dentry; - int err2 = 0; - error = nfserr_stale; do { tdentry = tdentry->d_parent; - if (exp->ex_dentry == tdentry) { - error = 0; + if (exp->ex_dentry == tdentry) break; - } - if ((err2 = nfsd_permission(exp, tdentry, MAY_READ))) { - error = err2; -#ifdef NFSD_PARANOIA - goto out1; -#else - goto out; -#endif + /* executable only by root and we can't be root */ + if (current->fsuid && + !(tdentry->d_inode->i_uid && + (tdentry->d_inode->i_mode & S_IXUSR)) && + !(tdentry->d_inode->i_gid && + (tdentry->d_inode->i_mode & S_IXGRP)) && + !(tdentry->d_inode->i_mode & S_IXOTH) && + (exp->ex_flags & NFSEXP_ROOTSQUASH)) { + error = nfserr_stale; +dprintk("fh_verify: no root_squashed access.\n"); } } while ((tdentry != tdentry->d_parent)); - if (error) { - printk("fh_verify: Security: %s/%s bad export.\n", + if (exp->ex_dentry != tdentry) { + error = nfserr_stale; + printk("nfsd Security: %s/%s bad export.\n", dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } } /* Finally, check access permissions. */ - error = nfsd_permission(exp, dentry, access); + if (!error) { + error = nfsd_permission(exp, dentry, access); + } #ifdef NFSD_PARANOIA -out1: if (error) printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, access, error); #endif - out: return error; } Index: linux/fs/nfsd/vfs.c diff -u linux/fs/nfsd/vfs.c:1.5 linux/fs/nfsd/vfs.c:1.5.2.1 --- linux/fs/nfsd/vfs.c:1.5 Sat Nov 7 16:43:38 1998 +++ linux/fs/nfsd/vfs.c Tue Nov 10 10:31:46 1998 @@ -148,16 +148,18 @@ dprintk("nfsd: nfsd_lookup(fh %p, %s)\n", SVCFH_DENTRY(fhp), name); /* Obtain dentry and export. */ - err = fh_verify(rqstp, fhp, S_IFDIR, MAY_NOP); + err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC); if (err) goto out; dparent = fhp->fh_dentry; exp = fhp->fh_export; +#if 0 err = nfsd_permission(exp, dparent, MAY_EXEC); if (err) goto out; +#endif err = nfserr_noent; if (fs_off_limits(dparent->d_sb)) goto out; @@ -232,13 +234,17 @@ dentry = fhp->fh_dentry; inode = dentry->d_inode; + err = inode_change_ok(inode, iap); + if (err) + goto out_nfserr; + /* The size case is special... */ if (iap->ia_valid & ATTR_SIZE) { if (!S_ISREG(inode->i_mode)) printk("nfsd_setattr: size change??\n"); if (iap->ia_size < inode->i_size) { err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC); - if (err != 0) + if (err) goto out; } err = get_write_access(inode); @@ -1228,8 +1234,7 @@ if (acc == MAY_NOP) return 0; - - /* +#if 0 dprintk("nfsd: permission 0x%x%s%s%s%s%s mode 0%o%s%s%s\n", acc, (acc & MAY_READ)? " read" : "", @@ -1243,8 +1248,7 @@ IS_RDONLY(inode)? " ro" : ""); dprintk(" owner %d/%d user %d/%d\n", inode->i_uid, inode->i_gid, current->fsuid, current->fsgid); - */ - +#endif #ifndef CONFIG_NFSD_SUN if (dentry->d_mounts != dentry) { return nfserr_perm; --------------------------------- G. Allen Morris III - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |