Skip to content

Commit

Permalink
ipc: get rid of ids->tables_initialized hack
Browse files Browse the repository at this point in the history
In sysvipc we have an ids->tables_initialized regarding the rhashtable,
introduced in 0cfb6ae ("ipc: optimize semget/shmget/msgget for lots
of keys")

It's there, specifically, to prevent nil pointer dereferences, from using
an uninitialized api.  Considering how rhashtable_init() can fail
(probably due to ENOMEM, if anything), this made the overall ipc
initialization capable of failure as well.  That alone is ugly, but fine,
however I've spotted a few issues regarding the semantics of
tables_initialized (however unlikely they may be):

- There is inconsistency in what we return to userspace: ipc_addid()
  returns ENOSPC which is certainly _wrong_, while ipc_obtain_object_idr()
  returns EINVAL.

- After we started using rhashtables, ipc_findkey() can return nil upon
  !tables_initialized, but the caller expects nil for when the ipc
  structure isn't found, and can therefore call into ipcget() callbacks.

Now that rhashtable initialization cannot fail, we can properly get rid of
the hack altogether.

[[email protected]: commit id extended to 12 digits]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Davidlohr Bueso <[email protected]>
Signed-off-by: Manfred Spraul <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: Herbert Xu <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Michael Kerrisk <[email protected]>
Cc: Michal Hocko <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Davidlohr Bueso authored and torvalds committed Aug 22, 2018
1 parent 2d22ecf commit dc2c8c8
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 16 deletions.
1 change: 0 additions & 1 deletion include/linux/ipc_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ struct user_namespace;
struct ipc_ids {
int in_use;
unsigned short seq;
bool tables_initialized;
struct rw_semaphore rwsem;
struct idr ipcs_idr;
int max_id;
Expand Down
23 changes: 8 additions & 15 deletions ipc/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ int ipc_init_ids(struct ipc_ids *ids)
if (err)
return err;
idr_init(&ids->ipcs_idr);
ids->tables_initialized = true;
ids->max_id = -1;
#ifdef CONFIG_CHECKPOINT_RESTORE
ids->next_id = -1;
Expand Down Expand Up @@ -179,19 +178,16 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
*/
static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
{
struct kern_ipc_perm *ipcp = NULL;
struct kern_ipc_perm *ipcp;

if (likely(ids->tables_initialized))
ipcp = rhashtable_lookup_fast(&ids->key_ht, &key,
ipcp = rhashtable_lookup_fast(&ids->key_ht, &key,
ipc_kht_params);
if (!ipcp)
return NULL;

if (ipcp) {
rcu_read_lock();
ipc_lock_object(ipcp);
return ipcp;
}

return NULL;
rcu_read_lock();
ipc_lock_object(ipcp);
return ipcp;
}

/*
Expand Down Expand Up @@ -269,7 +265,7 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)
if (limit > IPCMNI)
limit = IPCMNI;

if (!ids->tables_initialized || ids->in_use >= limit)
if (ids->in_use >= limit)
return -ENOSPC;

idr_preload(GFP_KERNEL);
Expand Down Expand Up @@ -578,9 +574,6 @@ struct kern_ipc_perm *ipc_obtain_object_idr(struct ipc_ids *ids, int id)
struct kern_ipc_perm *out;
int lid = ipcid_to_idx(id);

if (unlikely(!ids->tables_initialized))
return ERR_PTR(-EINVAL);

out = idr_find(&ids->ipcs_idr, lid);
if (!out)
return ERR_PTR(-EINVAL);
Expand Down

0 comments on commit dc2c8c8

Please sign in to comment.