[PATCH 1/2] rtnetlink: gate MAC address with an LSM hook

Jeffrey Vander Stoep jeffv at google.com
Wed Aug 21 13:55:52 UTC 2019


On Wed, Aug 21, 2019 at 3:45 PM Jeff Vander Stoep <jeffv at google.com> wrote:
>
> MAC addresses are often considered sensitive because they are
> usually unique and can be used to identify/track a device or
> user [1].
>
> The MAC address is accessible via the RTM_NEWLINK message type of a
> netlink route socket[2]. Ideally we could grant/deny access to the
> MAC address on a case-by-case basis without blocking the entire
> RTM_NEWLINK message type which contains a lot of other useful
> information. This can be achieved using a new LSM hook on the netlink
> message receive path. Using this new hook, individual LSMs can select
> which processes are allowed access to the real MAC, otherwise a
> default value of zeros is returned. Offloading access control
> decisions like this to an LSM is convenient because it preserves the
> status quo for most Linux users while giving the various LSMs
> flexibility to make finer grained decisions on access to sensitive
> data based on policy.
>
> [1] https://adamdrake.com/mac-addresses-udids-and-privacy.html
> [2] Other access vectors like ioctl(SIOCGIFHWADDR) are already covered
> by existing LSM hooks.
>
> Signed-off-by: Jeff Vander Stoep <jeffv at google.com>
> ---
>  include/linux/lsm_hooks.h |  8 ++++++++
>  include/linux/security.h  |  6 ++++++
>  net/core/rtnetlink.c      | 12 ++++++++++--
>  security/security.c       |  5 +++++
>  4 files changed, 29 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index df1318d85f7d..dfcb2e11ff43 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -728,6 +728,12 @@
>   *
>   * Security hooks for Netlink messaging.
>   *
> + * @netlink_receive
> + *     Check permissions on a netlink message field before populating it.
> + *     @sk associated sock of task receiving the message.
> + *     @skb contains the sk_buff structure for the netlink message.
> + *     Return 0 if the data should be included in the message.
> + *
>   * @netlink_send:
>   *     Save security information for a netlink message so that permission
>   *     checking can be performed when the message is processed.  The security
> @@ -1673,6 +1679,7 @@ union security_list_options {
>         int (*sem_semop)(struct kern_ipc_perm *perm, struct sembuf *sops,
>                                 unsigned nsops, int alter);
>
> +       int (*netlink_receive)(struct sock *sk, struct sk_buff *skb);
>         int (*netlink_send)(struct sock *sk, struct sk_buff *skb);
>
>         void (*d_instantiate)(struct dentry *dentry, struct inode *inode);
> @@ -1952,6 +1959,7 @@ struct security_hook_heads {
>         struct hlist_head sem_associate;
>         struct hlist_head sem_semctl;
>         struct hlist_head sem_semop;
> +       struct hlist_head netlink_receive;
>         struct hlist_head netlink_send;
>         struct hlist_head d_instantiate;
>         struct hlist_head getprocattr;
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 5f7441abbf42..46b5af6de59e 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -382,6 +382,7 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
>                          char **value);
>  int security_setprocattr(const char *lsm, const char *name, void *value,
>                          size_t size);
> +int security_netlink_receive(struct sock *sk, struct sk_buff *skb);
>  int security_netlink_send(struct sock *sk, struct sk_buff *skb);
>  int security_ismaclabel(const char *name);
>  int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
> @@ -1162,6 +1163,11 @@ static inline int security_setprocattr(const char *lsm, char *name,
>         return -EINVAL;
>  }
>
> +static inline int security_netlink_receive(struct sock *sk, struct sk_buff *skb)
> +{
> +       return 0;
> +}
> +
>  static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb)
>  {
>         return 0;
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 1ee6460f8275..7d69fcb8d22e 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -1650,8 +1650,16 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
>                 goto nla_put_failure;
>
>         if (dev->addr_len) {
> -               if (nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr) ||
> -                   nla_put(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast))
> +               if (skb->sk && security_netlink_receive(skb->sk, skb)) {
> +                       if (!nla_reserve(skb, IFLA_ADDRESS, dev->addr_len))
> +                               goto nla_put_failure;


Is populating the field with zeros the right approach or should I just
omit it entirely?
Even though this change will only impact LSM users I would still like to
minimize the potential for breakage of userspace processes. Returning the same
packet size and format seems like the least fragile thing to do.


>
> +
> +               } else {
> +                       if (nla_put(skb, IFLA_ADDRESS, dev->addr_len,
> +                                   dev->dev_addr))
> +                               goto nla_put_failure;
> +               }
> +               if (nla_put(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast))
>                         goto nla_put_failure;
>         }
>
> diff --git a/security/security.c b/security/security.c
> index 250ee2d76406..35c5929921b2 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1861,6 +1861,11 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
>         return -EINVAL;
>  }
>
> +int security_netlink_receive(struct sock *sk, struct sk_buff *skb)
> +{
> +       return call_int_hook(netlink_receive, 0, sk, skb);
> +}
> +
>  int security_netlink_send(struct sock *sk, struct sk_buff *skb)
>  {
>         return call_int_hook(netlink_send, 0, sk, skb);
> --
> 2.23.0.rc1.153.gdeed80330f-goog
>



More information about the Linux-security-module-archive mailing list