From a4907393a449a8c09953d47817856ea4838faf34 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 20 May 2008 19:34:39 -0400 Subject: [PATCH] --- yaml --- r: 101895 b: refs/heads/master c: 2116271a347d1181b5497602c2bfada1de8fd53b h: refs/heads/master i: 101893: e8a25723b3449d49bf031c28c3d4504f94e63856 101891: d726be9d99f9233510b6fb5eca0430d5f01e181a 101887: 55de5f296e9ae680893f507769021ead4ec8b020 v: v3 --- [refs] | 2 +- trunk/fs/nfs/file.c | 20 +++++++++++++++----- trunk/fs/nfs/proc.c | 24 ++++++++++++++++++++++++ trunk/include/linux/nfs_xdr.h | 1 + 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index 4ac64d2220a5..aaed4ea254b0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f3d47a3a6a1484a93c8cfe1e8c8d4399c95199c7 +refs/heads/master: 2116271a347d1181b5497602c2bfada1de8fd53b diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index d84a3d8f32af..7c73f06692b6 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -593,6 +593,7 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) { struct inode * inode = filp->f_mapping->host; + int ret = -ENOLCK; dprintk("NFS: nfs_lock(f=%s/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n", inode->i_sb->s_id, inode->i_ino, @@ -602,13 +603,22 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) /* No mandatory locks over NFS */ if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) - return -ENOLCK; + goto out_err; + + if (NFS_PROTO(inode)->lock_check_bounds != NULL) { + ret = NFS_PROTO(inode)->lock_check_bounds(fl); + if (ret < 0) + goto out_err; + } if (IS_GETLK(cmd)) - return do_getlk(filp, cmd, fl); - if (fl->fl_type == F_UNLCK) - return do_unlk(filp, cmd, fl); - return do_setlk(filp, cmd, fl); + ret = do_getlk(filp, cmd, fl); + else if (fl->fl_type == F_UNLCK) + ret = do_unlk(filp, cmd, fl); + else + ret = do_setlk(filp, cmd, fl); +out_err: + return ret; } /* diff --git a/trunk/fs/nfs/proc.c b/trunk/fs/nfs/proc.c index 03599bfe81cf..5c35b02857f3 100644 --- a/trunk/fs/nfs/proc.c +++ b/trunk/fs/nfs/proc.c @@ -598,6 +598,29 @@ nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); } +/* Helper functions for NFS lock bounds checking */ +#define NFS_LOCK32_OFFSET_MAX ((__s32)0x7fffffffUL) +static int nfs_lock_check_bounds(const struct file_lock *fl) +{ + __s32 start, end; + + start = (__s32)fl->fl_start; + if ((loff_t)start != fl->fl_start) + goto out_einval; + + if (fl->fl_end != OFFSET_MAX) { + end = (__s32)fl->fl_end; + if ((loff_t)end != fl->fl_end) + goto out_einval; + } else + end = NFS_LOCK32_OFFSET_MAX; + + if (start < 0 || start > end) + goto out_einval; + return 0; +out_einval: + return -EINVAL; +} const struct nfs_rpc_ops nfs_v2_clientops = { .version = 2, /* protocol version */ @@ -633,4 +656,5 @@ const struct nfs_rpc_ops nfs_v2_clientops = { .file_open = nfs_open, .file_release = nfs_release, .lock = nfs_proc_lock, + .lock_check_bounds = nfs_lock_check_bounds, }; diff --git a/trunk/include/linux/nfs_xdr.h b/trunk/include/linux/nfs_xdr.h index 24263bb8e0be..8d780de371f0 100644 --- a/trunk/include/linux/nfs_xdr.h +++ b/trunk/include/linux/nfs_xdr.h @@ -832,6 +832,7 @@ struct nfs_rpc_ops { int (*file_open) (struct inode *, struct file *); int (*file_release) (struct inode *, struct file *); int (*lock)(struct file *, int, struct file_lock *); + int (*lock_check_bounds)(const struct file_lock *); void (*clear_acl_cache)(struct inode *); };