diff options
| author | Jeff Layton <jlayton@poochiereds.net> | 2014-05-09 11:41:54 -0400 |
|---|---|---|
| committer | Jeff Layton <jlayton@poochiereds.net> | 2014-05-09 11:41:54 -0400 |
| commit | cf01f4eef9fe367ec0d85b38dd7214e29e376cdb (patch) | |
| tree | 2222f99e1cbc1979256996d7fa3bb42196acedfc | |
| parent | afcf0a2d9289bbe50aab362e6fb2798038815973 (diff) | |
locks: only validate the lock vs. f_mode in F_SETLK codepaths
v2: replace missing break in switch statement (as pointed out by Dave
Jones)
commit bce7560d4946 (locks: consolidate checks for compatible
filp->f_mode values in setlk handlers) introduced a regression in the
F_GETLK handler.
flock64_to_posix_lock is a shared codepath between F_GETLK and F_SETLK,
but the f_mode checks should only be applicable to the F_SETLK codepaths
according to POSIX.
Instead of just reverting the patch, add a new function to do this
checking and have the F_SETLK handlers call it.
Cc: Dave Jones <davej@redhat.com>
Reported-and-Tested-by: Reuben Farrelly <reuben@reub.net>
Signed-off-by: Jeff Layton <jlayton@poochiereds.net>
| -rw-r--r-- | fs/locks.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/fs/locks.c b/fs/locks.c index e663aeac579e..e390bd9ae068 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -389,18 +389,6 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, | |||
| 389 | fl->fl_ops = NULL; | 389 | fl->fl_ops = NULL; |
| 390 | fl->fl_lmops = NULL; | 390 | fl->fl_lmops = NULL; |
| 391 | 391 | ||
| 392 | /* Ensure that fl->fl_filp has compatible f_mode */ | ||
| 393 | switch (l->l_type) { | ||
| 394 | case F_RDLCK: | ||
| 395 | if (!(filp->f_mode & FMODE_READ)) | ||
| 396 | return -EBADF; | ||
| 397 | break; | ||
| 398 | case F_WRLCK: | ||
| 399 | if (!(filp->f_mode & FMODE_WRITE)) | ||
| 400 | return -EBADF; | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | |||
| 404 | return assign_type(fl, l->l_type); | 392 | return assign_type(fl, l->l_type); |
| 405 | } | 393 | } |
| 406 | 394 | ||
| @@ -2034,6 +2022,22 @@ static int do_lock_file_wait(struct file *filp, unsigned int cmd, | |||
| 2034 | return error; | 2022 | return error; |
| 2035 | } | 2023 | } |
| 2036 | 2024 | ||
| 2025 | /* Ensure that fl->fl_filp has compatible f_mode for F_SETLK calls */ | ||
| 2026 | static int | ||
| 2027 | check_fmode_for_setlk(struct file_lock *fl) | ||
| 2028 | { | ||
| 2029 | switch (fl->fl_type) { | ||
| 2030 | case F_RDLCK: | ||
| 2031 | if (!(fl->fl_file->f_mode & FMODE_READ)) | ||
| 2032 | return -EBADF; | ||
| 2033 | break; | ||
| 2034 | case F_WRLCK: | ||
| 2035 | if (!(fl->fl_file->f_mode & FMODE_WRITE)) | ||
| 2036 | return -EBADF; | ||
| 2037 | } | ||
| 2038 | return 0; | ||
| 2039 | } | ||
| 2040 | |||
| 2037 | /* Apply the lock described by l to an open file descriptor. | 2041 | /* Apply the lock described by l to an open file descriptor. |
| 2038 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). | 2042 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). |
| 2039 | */ | 2043 | */ |
| @@ -2071,6 +2075,10 @@ again: | |||
| 2071 | if (error) | 2075 | if (error) |
| 2072 | goto out; | 2076 | goto out; |
| 2073 | 2077 | ||
| 2078 | error = check_fmode_for_setlk(file_lock); | ||
| 2079 | if (error) | ||
| 2080 | goto out; | ||
| 2081 | |||
| 2074 | /* | 2082 | /* |
| 2075 | * If the cmd is requesting file-private locks, then set the | 2083 | * If the cmd is requesting file-private locks, then set the |
| 2076 | * FL_OFDLCK flag and override the owner. | 2084 | * FL_OFDLCK flag and override the owner. |
| @@ -2206,6 +2214,10 @@ again: | |||
| 2206 | if (error) | 2214 | if (error) |
| 2207 | goto out; | 2215 | goto out; |
| 2208 | 2216 | ||
| 2217 | error = check_fmode_for_setlk(file_lock); | ||
| 2218 | if (error) | ||
| 2219 | goto out; | ||
| 2220 | |||
| 2209 | /* | 2221 | /* |
| 2210 | * If the cmd is requesting file-private locks, then set the | 2222 | * If the cmd is requesting file-private locks, then set the |
| 2211 | * FL_OFDLCK flag and override the owner. | 2223 | * FL_OFDLCK flag and override the owner. |
