From patchwork Sun Jul 30 17:24:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jamal Hadi Salim X-Patchwork-Id: 795398 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mojatatu-com.20150623.gappssmtp.com header.i=@mojatatu-com.20150623.gappssmtp.com header.b="GJOAc5tK"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3xL8c24yFzz9s81 for ; Mon, 31 Jul 2017 03:25:22 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754404AbdG3RZH (ORCPT ); Sun, 30 Jul 2017 13:25:07 -0400 Received: from mail-io0-f195.google.com ([209.85.223.195]:38893 "EHLO mail-io0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754298AbdG3RZE (ORCPT ); Sun, 30 Jul 2017 13:25:04 -0400 Received: by mail-io0-f195.google.com with SMTP id l7so17765197iof.5 for ; Sun, 30 Jul 2017 10:25:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mojatatu-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GVGlXBh5aAlAF4yXIu6t9NbSeKL1HD+yHMroLk7Jcwk=; b=GJOAc5tK7CzJ7dnooSTVlHj5VvLdEr0mY4ltNj5BJpVvKb+wT14kh0lMbHk+o/5amI MiHxQBHLQQ90XUmBrIV2+lFJ1v030Mvbpspst9x2yA5V+ccqS3F/5Nf2hxE2InCUS6ad zWiJ6cHjQLDVL1A5ciwqZxTCHz5rw4NloKdiasnBiKj0u0/w2Fpz8aczvUqqlngnhn5B WPeWBQoIbVZLM/Msjunr3DjMLHvJAkHQ/u5f4ZYWv3PpyFyAKg/27BqHaG2mJvTE8oAZ UCxirkVcaKKc1RTOMQL4vOeS6Fnjd891jOPY1Wf5SEZzyAf2mtcu+ZRBnOTVyn3ywwBI 76XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GVGlXBh5aAlAF4yXIu6t9NbSeKL1HD+yHMroLk7Jcwk=; b=MZA04HkCoxIVBGiMbyC/1Lii45Q9737dJ7RUeHlDCbmLOMTulyxHZIUhz8l2woCtJi ytwzvgTcA9eHypfwU5W9+C/Dc9zQq5VNU+FhWfot0CZ6xDaH7keLMLA5Bac57ryFBzbG BXKyD2M03Y/amAsonMvWL79f+B/fKJC2yWFOLZXA2gW8ws7Pyz+YLG+OkGJxdVDRNJo6 3hgcJ+aKWx2TWdOrdpDlaTGuF9m+T+BU9XtUZdN7tCgwO7NalP1nidk+udqwKuRYeiT0 X79n5Y/AKHjT10DpLS3cj27Tcrcv2b97Wh5xsThO0jSjJMLZ25Bp7QBRzSxt66WhEiTC jjnQ== X-Gm-Message-State: AIVw1101VO+unj7CIHQoep+Oqu4ZehsJsoS449Cr+PBh8RPqh+JbcrIH 77ImIi1DXLB+jprK X-Received: by 10.107.187.4 with SMTP id l4mr15981093iof.137.1501435503405; Sun, 30 Jul 2017 10:25:03 -0700 (PDT) Received: from localhost.localdomain (135-23-93-187.cpe.pppoe.ca. [135.23.93.187]) by smtp.gmail.com with ESMTPSA id a70sm12440814ioe.88.2017.07.30.10.25.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 30 Jul 2017 10:25:02 -0700 (PDT) From: Jamal Hadi Salim X-Google-Original-From: Jamal Hadi Salim To: davem@davemloft.net Cc: netdev@vger.kernel.org, jiri@resnulli.us, xiyou.wangcong@gmail.com, eric.dumazet@gmail.com, horms@verge.net.au, dsahern@gmail.com, Jamal Hadi Salim Subject: [PATCH net-next v12 1/4] net netlink: Add new type NLA_BITFIELD32 Date: Sun, 30 Jul 2017 13:24:49 -0400 Message-Id: <1501435492-28301-2-git-send-email-jhs@emojatatu.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1501435492-28301-1-git-send-email-jhs@emojatatu.com> References: <1501435492-28301-1-git-send-email-jhs@emojatatu.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Jamal Hadi Salim Generic bitflags attribute content sent to the kernel by user. With this netlink attr type the user can either set or unset a flag in the kernel. The value is a bitmap that defines the bit values being set The selector is a bitmask that defines which value bit is to be considered. A check is made to ensure the rules that a kernel subsystem always conforms to bitflags the kernel already knows about. i.e if the user tries to set a bit flag that is not understood then the _it will be rejected_. In the most basic form, the user specifies the attribute policy as: [ATTR_GOO] = { .type = NLA_BITFIELD32, .validation_data = &myvalidflags }, where myvalidflags is the bit mask of the flags the kernel understands. If the user _does not_ provide myvalidflags then the attribute will also be rejected. Examples: value = 0x0, and selector = 0x1 implies we are selecting bit 1 and we want to set its value to 0. value = 0x2, and selector = 0x2 implies we are selecting bit 2 and we want to set its value to 1. Suggested-by: Jiri Pirko Signed-off-by: Jamal Hadi Salim --- include/net/netlink.h | 16 ++++++++++++++++ include/uapi/linux/netlink.h | 17 +++++++++++++++++ lib/nlattr.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/include/net/netlink.h b/include/net/netlink.h index ef8e6c3..82dd298 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -178,6 +178,7 @@ enum { NLA_S16, NLA_S32, NLA_S64, + NLA_BITFIELD32, __NLA_TYPE_MAX, }; @@ -206,6 +207,7 @@ enum { * NLA_MSECS Leaving the length field zero will verify the * given type fits, using it verifies minimum length * just like "All other" + * NLA_BITFIELD32 A 32-bit bitmap/bitselector attribute * All other Minimum length of attribute payload * * Example: @@ -213,11 +215,13 @@ enum { * [ATTR_FOO] = { .type = NLA_U16 }, * [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ }, * [ATTR_BAZ] = { .len = sizeof(struct mystruct) }, + * [ATTR_GOO] = { .type = NLA_BITFIELD32, .validation_data = &myvalidflags }, * }; */ struct nla_policy { u16 type; u16 len; + void *validation_data; }; /** @@ -1203,6 +1207,18 @@ static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla) } /** + * nla_get_bitfield32 - return payload of 32 bitfield attribute + * @nla: nla_bitfield32 attribute + */ +static inline struct nla_bitfield32 nla_get_bitfield32(const struct nlattr *nla) +{ + struct nla_bitfield32 tmp; + + nla_memcpy(&tmp, nla, sizeof(tmp)); + return tmp; +} + +/** * nla_memdup - duplicate attribute memory (kmemdup) * @src: netlink attribute to duplicate from * @gfp: GFP mask diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h index f86127a..f4fc9c9 100644 --- a/include/uapi/linux/netlink.h +++ b/include/uapi/linux/netlink.h @@ -226,5 +226,22 @@ struct nlattr { #define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) +/* Generic 32 bitflags attribute content sent to the kernel. + * + * The value is a bitmap that defines the values being set + * The selector is a bitmask that defines which value is legit + * + * Examples: + * value = 0x0, and selector = 0x1 + * implies we are selecting bit 1 and we want to set its value to 0. + * + * value = 0x2, and selector = 0x2 + * implies we are selecting bit 2 and we want to set its value to 1. + * + */ +struct nla_bitfield32 { + __u32 value; + __u32 selector; +}; #endif /* _UAPI__LINUX_NETLINK_H */ diff --git a/lib/nlattr.c b/lib/nlattr.c index fb52435..ee79b7a 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -27,6 +27,30 @@ [NLA_S64] = sizeof(s64), }; +static int validate_nla_bitfield32(const struct nlattr *nla, + u32 *valid_flags_allowed) +{ + const struct nla_bitfield32 *bf = nla_data(nla); + u32 *valid_flags_mask = valid_flags_allowed; + + if (!valid_flags_allowed) + return -EINVAL; + + /*disallow invalid bit selector */ + if (bf->selector & ~*valid_flags_mask) + return -EINVAL; + + /*disallow invalid bit values */ + if (bf->value & ~*valid_flags_mask) + return -EINVAL; + + /*disallow valid bit values that are not selected*/ + if (bf->value & ~bf->selector) + return -EINVAL; + + return 0; +} + static int validate_nla(const struct nlattr *nla, int maxtype, const struct nla_policy *policy) { @@ -46,6 +70,12 @@ static int validate_nla(const struct nlattr *nla, int maxtype, return -ERANGE; break; + case NLA_BITFIELD32: + if (attrlen != sizeof(struct nla_bitfield32)) + return -ERANGE; + + return validate_nla_bitfield32(nla, pt->validation_data); + case NLA_NUL_STRING: if (pt->len) minlen = min_t(int, attrlen, pt->len + 1);