On Mon, May 15, 2017 at 10:19 AM, Manfred Spraul
<manf...@colorfullife.com> wrote:
> ipc has two management structures that exist for every id:
> - struct kern_ipc_perm, it contains e.g. the permissions.
> - struct ipc_rcu, it contains the rcu head for rcu handling and
>   the refcount.
>
> The patch merges both structures.
> As a bonus, we may save one cacheline, because both structures are
> cacheline aligned.
> In addition, it reduces the number of casts, instead most codepaths can
> use container_of.
>
> Signed-off-by: Manfred Spraul <manf...@colorfullife.com>
> ---
>  include/linux/ipc.h |  3 +++
>  ipc/msg.c           | 22 ++++++++++++++--------
>  ipc/sem.c           | 35 ++++++++++++++++++++---------------
>  ipc/shm.c           | 21 ++++++++++++++-------
>  ipc/util.c          | 33 +++++++++++++++------------------
>  ipc/util.h          | 18 +++++++-----------
>  6 files changed, 73 insertions(+), 59 deletions(-)
>
> diff --git a/include/linux/ipc.h b/include/linux/ipc.h
> index 71fd92d..5591f055 100644
> --- a/include/linux/ipc.h
> +++ b/include/linux/ipc.h
> @@ -20,6 +20,9 @@ struct kern_ipc_perm {
>         umode_t         mode;
>         unsigned long   seq;
>         void            *security;
> +
> +       struct rcu_head rcu;
> +       atomic_t refcount;
>  } ____cacheline_aligned_in_smp;
>
>  #endif /* _LINUX_IPC_H */
> diff --git a/ipc/msg.c b/ipc/msg.c
> index 104926d..e9785c4 100644
> --- a/ipc/msg.c
> +++ b/ipc/msg.c
> @@ -97,8 +97,8 @@ static inline void msg_rmid(struct ipc_namespace *ns, 
> struct msg_queue *s)
>
>  static void msg_rcu_free(struct rcu_head *head)
>  {
> -       struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu);
> -       struct msg_queue *msq = ipc_rcu_to_struct(p);
> +       struct kern_ipc_perm *p = container_of(head, struct kern_ipc_perm, 
> rcu);
> +       struct msg_queue *msq = container_of(p, struct msg_queue, q_perm);
>
>         security_msg_queue_free(msq);
>         ipc_rcu_free(head);
> @@ -118,7 +118,13 @@ static int newque(struct ipc_namespace *ns, struct 
> ipc_params *params)
>         key_t key = params->key;
>         int msgflg = params->flg;
>
> -       msq = ipc_rcu_alloc(sizeof(*msq));
> +       if (offsetof(struct msg_queue, q_perm) != 0) {
> +               pr_err("Invalid struct sem_perm, failing msgget().\n");
> +               return -ENOMEM;
> +       }

This is a compile-time check that will result in a runtime warning.
This should be a BUILD_BUG_ON() instead. It means we can't randomize
the first element of these structures, but I'll deal with that in the
randstruct plugin (or send another fix when I dig through it).

It looks like the "as first element" is needed to share the alloc/put
routines. To randomize the position of kern_ipc_perm within each
structure means having different accessor functions, which makes this
less fun. :P

Anyway, regardless, these patches make the sem_base thing go away and
consolidates other stuff which looks good to me.

Thanks!

-Kees

-- 
Kees Cook
Pixel Security

Reply via email to