summaryrefslogtreecommitdiffstats
path: root/xlators/features
diff options
context:
space:
mode:
authorPranith Kumar K <pkarampu@redhat.com>2019-04-01 11:14:56 +0530
committerAmar Tumballi <amarts@redhat.com>2019-04-26 06:51:24 +0000
commita9143223c515b82f6382f1372dfbdc0439dba198 (patch)
treed04a656ed522d6ad0e2ddcd4b2ed15beb30cf449 /xlators/features
parentedeb0d6e616cf4750ea9f6b6245631de8db233cf (diff)
features/locks: error-out {inode,entry}lk fops with all-zero lk-owner
Problem: Sometimes we find that developers forget to assign lk-owner for an inodelk/entrylk/lk before writing code to wind these fops. locks xlator at the moment allows this operation. This leads to multiple threads in the same client being able to get locks on the inode because lk-owner is same and transport is same. So isolation with locks can't be achieved. Fix: Disallow locks with lk-owner zero. fixes bz#1624701 Change-Id: I1aadcfbaaa4d49308f7c819505857e201809b3bc Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
Diffstat (limited to 'xlators/features')
-rw-r--r--xlators/features/locks/src/common.c28
-rw-r--r--xlators/features/locks/src/common.h5
-rw-r--r--xlators/features/locks/src/entrylk.c12
-rw-r--r--xlators/features/locks/src/inodelk.c16
-rw-r--r--xlators/features/locks/src/posix.c7
5 files changed, 53 insertions, 15 deletions
diff --git a/xlators/features/locks/src/common.c b/xlators/features/locks/src/common.c
index 9e06484308e..0a9c9293f01 100644
--- a/xlators/features/locks/src/common.c
+++ b/xlators/features/locks/src/common.c
@@ -493,7 +493,8 @@ unlock:
/* Create a new posix_lock_t */
posix_lock_t *
new_posix_lock(struct gf_flock *flock, client_t *client, pid_t client_pid,
- gf_lkowner_t *owner, fd_t *fd, uint32_t lk_flags, int blocking)
+ gf_lkowner_t *owner, fd_t *fd, uint32_t lk_flags, int blocking,
+ int32_t *op_errno)
{
posix_lock_t *lock = NULL;
@@ -501,8 +502,14 @@ new_posix_lock(struct gf_flock *flock, client_t *client, pid_t client_pid,
GF_VALIDATE_OR_GOTO("posix-locks", client, out);
GF_VALIDATE_OR_GOTO("posix-locks", fd, out);
+ if (!pl_is_lk_owner_valid(owner, client)) {
+ *op_errno = EINVAL;
+ goto out;
+ }
+
lock = GF_CALLOC(1, sizeof(posix_lock_t), gf_locks_mt_posix_lock_t);
if (!lock) {
+ *op_errno = ENOMEM;
goto out;
}
@@ -520,6 +527,7 @@ new_posix_lock(struct gf_flock *flock, client_t *client, pid_t client_pid,
if (lock->client_uid == NULL) {
GF_FREE(lock);
lock = NULL;
+ *op_errno = ENOMEM;
goto out;
}
@@ -988,6 +996,7 @@ pl_send_prelock_unlock(xlator_t *this, pl_inode_t *pl_inode,
0,
};
posix_lock_t *unlock_lock = NULL;
+ int32_t op_errno = 0;
struct list_head granted_list;
posix_lock_t *tmp = NULL;
@@ -1005,7 +1014,7 @@ pl_send_prelock_unlock(xlator_t *this, pl_inode_t *pl_inode,
unlock_lock = new_posix_lock(&flock, old_lock->client, old_lock->client_pid,
&old_lock->owner, old_lock->fd,
- old_lock->lk_flags, 0);
+ old_lock->lk_flags, 0, &op_errno);
GF_VALIDATE_OR_GOTO(this->name, unlock_lock, out);
ret = 0;
@@ -1272,4 +1281,17 @@ pl_local_init(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd)
}
return 0;
-} \ No newline at end of file
+}
+
+gf_boolean_t
+pl_is_lk_owner_valid(gf_lkowner_t *owner, client_t *client)
+{
+ if (client && (client->opversion < GD_OP_VERSION_7_0)) {
+ return _gf_true;
+ }
+
+ if (is_lk_owner_null(owner)) {
+ return _gf_false;
+ }
+ return _gf_true;
+}
diff --git a/xlators/features/locks/src/common.h b/xlators/features/locks/src/common.h
index 3a7496758ab..55603ef9c42 100644
--- a/xlators/features/locks/src/common.h
+++ b/xlators/features/locks/src/common.h
@@ -51,7 +51,8 @@
posix_lock_t *
new_posix_lock(struct gf_flock *flock, client_t *client, pid_t client_pid,
- gf_lkowner_t *owner, fd_t *fd, uint32_t lk_flags, int can_block);
+ gf_lkowner_t *owner, fd_t *fd, uint32_t lk_flags, int blocking,
+ int32_t *op_errno);
pl_inode_t *
pl_inode_get(xlator_t *this, inode_t *inode, pl_local_t *local);
@@ -212,4 +213,6 @@ pl_clean_local(pl_local_t *local);
int
pl_local_init(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd);
+gf_boolean_t
+pl_is_lk_owner_valid(gf_lkowner_t *owner, client_t *client);
#endif /* __COMMON_H__ */
diff --git a/xlators/features/locks/src/entrylk.c b/xlators/features/locks/src/entrylk.c
index ced5eca2749..9d6a4c93057 100644
--- a/xlators/features/locks/src/entrylk.c
+++ b/xlators/features/locks/src/entrylk.c
@@ -39,13 +39,20 @@ __pl_entrylk_ref(pl_entry_lock_t *lock)
static pl_entry_lock_t *
new_entrylk_lock(pl_inode_t *pinode, const char *basename, entrylk_type type,
- const char *domain, call_frame_t *frame, char *conn_id)
+ const char *domain, call_frame_t *frame, char *conn_id,
+ int32_t *op_errno)
{
pl_entry_lock_t *newlock = NULL;
+ if (!pl_is_lk_owner_valid(&frame->root->lk_owner, frame->root->client)) {
+ *op_errno = EINVAL;
+ goto out;
+ }
+
newlock = GF_CALLOC(1, sizeof(pl_entry_lock_t),
gf_locks_mt_pl_entry_lock_t);
if (!newlock) {
+ *op_errno = ENOMEM;
goto out;
}
@@ -793,10 +800,9 @@ pl_common_entrylk(call_frame_t *frame, xlator_t *this, const char *volume,
entrylk_trace_in(this, frame, volume, fd, loc, basename, cmd, type);
reqlock = new_entrylk_lock(pinode, basename, type, dom->domain, frame,
- conn_id);
+ conn_id, &op_errno);
if (!reqlock) {
op_ret = -1;
- op_errno = ENOMEM;
goto unwind;
}
diff --git a/xlators/features/locks/src/inodelk.c b/xlators/features/locks/src/inodelk.c
index df00ede242d..95afc902ffa 100644
--- a/xlators/features/locks/src/inodelk.c
+++ b/xlators/features/locks/src/inodelk.c
@@ -873,17 +873,23 @@ pl_inode_setlk(xlator_t *this, pl_ctx_t *ctx, pl_inode_t *pl_inode,
}
/* Create a new inode_lock_t */
-pl_inode_lock_t *
+static pl_inode_lock_t *
new_inode_lock(struct gf_flock *flock, client_t *client, pid_t client_pid,
call_frame_t *frame, xlator_t *this, const char *volume,
- char *conn_id)
+ char *conn_id, int32_t *op_errno)
{
pl_inode_lock_t *lock = NULL;
+ if (!pl_is_lk_owner_valid(&frame->root->lk_owner, frame->root->client)) {
+ *op_errno = EINVAL;
+ goto out;
+ }
+
lock = GF_CALLOC(1, sizeof(*lock), gf_locks_mt_pl_inode_lock_t);
if (!lock) {
- return NULL;
+ *op_errno = ENOMEM;
+ goto out;
}
lock->fl_start = flock->l_start;
@@ -911,6 +917,7 @@ new_inode_lock(struct gf_flock *flock, client_t *client, pid_t client_pid,
INIT_LIST_HEAD(&lock->contend);
__pl_inodelk_ref(lock);
+out:
return lock;
}
@@ -1005,11 +1012,10 @@ pl_common_inodelk(call_frame_t *frame, xlator_t *this, const char *volume,
}
reqlock = new_inode_lock(flock, frame->root->client, frame->root->pid,
- frame, this, dom->domain, conn_id);
+ frame, this, dom->domain, conn_id, &op_errno);
if (!reqlock) {
op_ret = -1;
- op_errno = ENOMEM;
goto unwind;
}
diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c
index 9d7210f1bb5..d2fc82feacb 100644
--- a/xlators/features/locks/src/posix.c
+++ b/xlators/features/locks/src/posix.c
@@ -2302,9 +2302,10 @@ __fd_has_locks(pl_inode_t *pl_inode, fd_t *fd)
static posix_lock_t *
lock_dup(posix_lock_t *lock)
{
+ int32_t op_errno = 0;
return new_posix_lock(&lock->user_flock, lock->client, lock->client_pid,
&lock->owner, (fd_t *)lock->fd_num, lock->lk_flags,
- lock->blocking);
+ lock->blocking, &op_errno);
}
static int
@@ -2521,11 +2522,11 @@ pl_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd,
}
reqlock = new_posix_lock(flock, frame->root->client, frame->root->pid,
- &frame->root->lk_owner, fd, lk_flags, can_block);
+ &frame->root->lk_owner, fd, lk_flags, can_block,
+ &op_errno);
if (!reqlock) {
op_ret = -1;
- op_errno = ENOMEM;
goto unwind;
}