patch-2.2.0-pre2 linux/fs/nfsd/vfs.c
Next file: linux/fs/open.c
Previous file: linux/fs/nfsd/stats.c
Back to the patch index
Back to the overall index
- Lines: 233
- Date:
Tue Dec 29 11:42:25 1998
- Orig file:
v2.2.0-pre1/linux/fs/nfsd/vfs.c
- Orig date:
Tue Dec 22 14:16:57 1998
diff -u --recursive --new-file v2.2.0-pre1/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
@@ -73,9 +73,10 @@
p_rawin;
};
-#define FILECACHE_MAX (2 * NFSD_MAXSERVS)
-static struct raparms raparms[FILECACHE_MAX];
-static struct raparms * raparm_cache = 0;
+int nfsd_nservers = 0;
+#define FILECACHE_MAX (2 * nfsd_nservers)
+static struct raparms * raparml = NULL;
+static struct raparms * raparm_cache = NULL;
/*
* Lock a parent directory following the VFS locking protocol.
@@ -148,16 +149,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 +235,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);
@@ -275,9 +282,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))
@@ -493,6 +508,9 @@
struct inode *inode;
mm_segment_t oldfs;
int err = 0;
+#ifdef CONFIG_QUOTA
+ uid_t saved_euid;
+#endif
if (!cnt)
goto out;
@@ -522,16 +540,31 @@
/* Write the data. */
oldfs = get_fs(); set_fs(KERNEL_DS);
+#ifdef CONFIG_QUOTA
+ /* This is for disk quota. */
+ saved_euid = current->euid;
+ current->euid = current->fsuid;
err = file.f_op->write(&file, buf, cnt, &file.f_pos);
+ current->euid = saved_euid;
+#else
+ err = file.f_op->write(&file, buf, cnt, &file.f_pos);
+#endif
set_fs(oldfs);
/* 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 */
@@ -661,7 +694,14 @@
break;
case S_IFCHR:
case S_IFBLK:
+ /* The client is _NOT_ required to do security enforcement */
+ if(!capable(CAP_SYS_ADMIN))
+ {
+ err = -EPERM;
+ goto out;
+ }
case S_IFIFO:
+ case S_IFSOCK:
opfunc = dirp->i_op->mknod;
break;
}
@@ -719,6 +759,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)
@@ -736,7 +777,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)
@@ -1235,11 +1282,11 @@
{
struct inode *inode = dentry->d_inode;
int err;
+ kernel_cap_t saved_cap;
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" : "",
@@ -1253,8 +1300,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;
@@ -1284,15 +1330,33 @@
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)
+ if (err == -EACCES && 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;
}
+void
+nfsd_racache_shutdown(void)
+{
+ if (!raparm_cache)
+ return;
+ dprintk("nfsd: freeing %d readahead buffers.\n", FILECACHE_MAX);
+ kfree(raparml);
+ nfsd_nservers = 0;
+ raparm_cache = raparml = NULL;
+}
/*
* Initialize readahead param cache
*/
@@ -1303,9 +1367,19 @@
if (raparm_cache)
return;
- memset(raparms, 0, sizeof(raparms));
- for (i = 0; i < FILECACHE_MAX - 1; i++) {
- raparms[i].p_next = raparms + i + 1;
+ raparml = kmalloc(sizeof(struct raparms) * FILECACHE_MAX, GFP_KERNEL);
+
+ if (raparml != NULL) {
+ dprintk("nfsd: allocating %d readahead buffers.\n",
+ FILECACHE_MAX);
+ memset(raparml, 0, sizeof(struct raparms) * FILECACHE_MAX);
+ for (i = 0; i < FILECACHE_MAX - 1; i++) {
+ raparml[i].p_next = raparml + i + 1;
+ }
+ raparm_cache = raparml;
+ } else {
+ printk(KERN_WARNING
+ "nfsd: Could not allocate memory read-ahead cache.\n");
+ nfsd_nservers = 0;
}
- raparm_cache = raparms;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov