Thanks for your bug report. Here is a patch. It is for Linux 2.1.123.
I think it should work for recent kernels also. Please let me know
if it fixes all the ro,root_squash bugs you have. If not, please
tell me how to recreate the bug. I am planning to make a new knfsd
soon.
H.J.
----
Index: fs/nfsd/vfs.c
===================================================================
RCS file: /home/work/cvs/linux/linux/fs/nfsd/vfs.c,v
retrieving revision 1.5
diff -u -r1.5 vfs.c
--- fs/nfsd/vfs.c 1998/09/29 14:33:26 1.5
+++ fs/nfsd/vfs.c 1998/09/30 03:17:21
@@ -267,9 +274,17 @@
/* Change the attributes. */
if (iap->ia_valid) {
+ kernel_cap_t saved_cap;
+
iap->ia_valid |= ATTR_CTIME;
iap->ia_ctime = CURRENT_TIME;
+ if (current->fsuid != 0) {
+ saved_cap = current->cap_effective;
+ cap_clear(current->cap_effective);
+ }
err = notify_change(dentry, iap);
+ if (current->fsuid != 0)
+ current->cap_effective = saved_cap;
if (err)
goto out_nfserr;
if (EX_ISSYNC(fhp->fh_export))
@@ -531,10 +546,17 @@
/* clear setuid/setgid flag after write */
if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {
struct iattr ia;
+ kernel_cap_t saved_cap;
ia.ia_valid = ATTR_MODE;
ia.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
+ if (current->fsuid != 0) {
+ saved_cap = current->cap_effective;
+ cap_clear(current->cap_effective);
+ }
notify_change(dentry, &ia);
+ if (current->fsuid != 0)
+ current->cap_effective = saved_cap;
}
fh_unlock(fhp); /* unlock inode */
@@ -726,6 +748,7 @@
struct inode *inode;
struct iattr newattrs;
int err;
+ kernel_cap_t saved_cap;
err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE | MAY_TRUNC);
if (err)
@@ -743,7 +766,13 @@
DQUOT_INIT(inode);
newattrs.ia_size = size;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+ if (current->fsuid != 0) {
+ saved_cap = current->cap_effective;
+ cap_clear(current->cap_effective);
+ }
err = notify_change(dentry, &newattrs);
+ if (current->fsuid != 0)
+ current->cap_effective = saved_cap;
if (!err) {
vmtruncate(inode, size);
if (inode->i_op && inode->i_op->truncate)
@@ -1232,6 +1261,7 @@
{
struct inode *inode = dentry->d_inode;
int err;
+ kernel_cap_t saved_cap;
if (acc == MAY_NOP)
return 0;
@@ -1275,11 +1312,19 @@
if (inode->i_uid == current->fsuid /* && !(acc & MAY_TRUNC) */)
return 0;
+ if (current->fsuid != 0) {
+ saved_cap = current->cap_effective;
+ cap_clear(current->cap_effective);
+ }
+
err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC));
/* Allow read access to binaries even when mode 111 */
if (err == -EPERM && S_ISREG(inode->i_mode) && acc == MAY_READ)
err = permission(inode, MAY_EXEC);
+
+ if (current->fsuid != 0)
+ current->cap_effective = saved_cap;
return err? nfserrno(-err) : 0;
}
-
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/