Fix length of buffer copied in __nfs4_get_acl_uncached
[linux-flexiantxendom0.git] / fs / nfs / nfs4proc.c
index 979ccc3..6cc5755 100644 (file)
@@ -3617,7 +3617,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
                if (acl_len > buflen)
                        goto out_free;
                _copy_from_pages(buf, pages, res.acl_data_offset,
-                               res.acl_len);
+                               acl_len);
        }
        ret = acl_len;
 out_free:
@@ -4453,7 +4453,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
 static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
-       struct nfs4_exception exception = { };
+       struct nfs4_exception exception = {
+               .inode = state->inode,
+       };
        int err;
 
        do {
@@ -4471,7 +4473,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
 static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
-       struct nfs4_exception exception = { };
+       struct nfs4_exception exception = {
+               .inode = state->inode,
+       };
        int err;
 
        err = nfs4_set_lock_state(state, request);
@@ -4551,6 +4555,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
 {
        struct nfs4_exception exception = {
                .state = state,
+               .inode = state->inode,
        };
        int err;
 
@@ -4596,6 +4601,20 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
 
        if (state == NULL)
                return -ENOLCK;
+       /*
+        * Don't rely on the VFS having checked the file open mode,
+        * since it won't do this for flock() locks.
+        */
+       switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) {
+       case F_RDLCK:
+               if (!(filp->f_mode & FMODE_READ))
+                       return -EBADF;
+               break;
+       case F_WRLCK:
+               if (!(filp->f_mode & FMODE_WRITE))
+                       return -EBADF;
+       }
+
        do {
                status = nfs4_proc_setlk(state, cmd, request);
                if ((status != -EAGAIN) || IS_SETLK(cmd))