Skip to content

Commit

Permalink
ipc sem: use kvmalloc for sem_undo allocation
Browse files Browse the repository at this point in the history
Patch series "ipc: allocations cleanup", v2.

Some ipc objects use the wrong allocation functions: small objects can use
kmalloc(), and vice versa, potentially large objects can use kmalloc().

This patch (of 2):

Size of sem_undo can exceed one page and with the maximum possible nsems =
32000 it can grow up to 64Kb.  Let's switch its allocation to kvmalloc to
avoid user-triggered disruptive actions like OOM killer in case of
high-order memory shortage.

User triggerable high order allocations are quite a problem on heavily
fragmented systems.  They can be a DoS vector.

Link: https://lkml.kernel.org/r/[email protected]
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Vasily Averin <[email protected]>
Acked-by: Michal Hocko <[email protected]>
Reviewed-by: Shakeel Butt <[email protected]>
Acked-by: Roman Gushchin <[email protected]>
Cc: Alexey Dobriyan <[email protected]>
Cc: Davidlohr Bueso <[email protected]>
Cc: Dmitry Safonov <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Manfred Spraul <[email protected]>
Cc: Vladimir Davydov <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
vaverin authored and torvalds committed Jul 1, 2021
1 parent 3b52348 commit fc37a3b
Showing 1 changed file with 6 additions and 5 deletions.
11 changes: 6 additions & 5 deletions ipc/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
un->semid = -1;
list_del_rcu(&un->list_proc);
spin_unlock(&un->ulp->lock);
kfree_rcu(un, rcu);
kvfree_rcu(un, rcu);
}

/* Wake up all pending processes and let them fail with EIDRM. */
Expand Down Expand Up @@ -1937,7 +1937,8 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
rcu_read_unlock();

/* step 2: allocate new undo structure */
new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
new = kvzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems,
GFP_KERNEL);
if (!new) {
ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
return ERR_PTR(-ENOMEM);
Expand All @@ -1949,7 +1950,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
if (!ipc_valid_object(&sma->sem_perm)) {
sem_unlock(sma, -1);
rcu_read_unlock();
kfree(new);
kvfree(new);
un = ERR_PTR(-EIDRM);
goto out;
}
Expand All @@ -1960,7 +1961,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
*/
un = lookup_undo(ulp, semid);
if (un) {
kfree(new);
kvfree(new);
goto success;
}
/* step 5: initialize & link new undo structure */
Expand Down Expand Up @@ -2420,7 +2421,7 @@ void exit_sem(struct task_struct *tsk)
rcu_read_unlock();
wake_up_q(&wake_q);

kfree_rcu(un, rcu);
kvfree_rcu(un, rcu);
}
kfree(ulp);
}
Expand Down

0 comments on commit fc37a3b

Please sign in to comment.