Skip to content

Commit 89d3552

Browse files
dsaherndavem330
authored andcommitted
netlink: Add new socket option to enable strict checking on dumps
Add a new socket option, NETLINK_DUMP_STRICT_CHK, that userspace can use via setsockopt to request strict checking of headers and attributes on dump requests. To get dump features such as kernel side filtering based on data in the header or attributes appended to the dump request, userspace must call setsockopt() for NETLINK_DUMP_STRICT_CHK and a non-zero value. Since the netlink sock and its flags are private to the af_netlink code, the strict checking flag is passed to dump handlers via a flag in the netlink_callback struct. For old userspace on new kernel there is no impact as all of the data checks in later patches are wrapped in a check on the new strict flag. For new userspace on old kernel, the setsockopt will fail and even if new userspace sets data in the headers and appended attributes the kernel will silently ignore it. Moving forward when the setsockopt succeeds, the new userspace on old kernel means the dump request can pass an attribute the kernel does not understand. The dump will then fail as the older kernel does not understand it. New userspace on new kernel setting the socket option gets the benefit of the improved data dump. Kernel side the NETLINK_DUMP_STRICT_CHK uapi is converted to a generic NETLINK_F_STRICT_CHK flag which can potentially be leveraged for tighter checking on the NEW, DEL, and SET commands. Signed-off-by: David Ahern <[email protected]> Acked-by: Christian Brauner <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6ba1e6e commit 89d3552

File tree

4 files changed

+23
-1
lines changed

4 files changed

+23
-1
lines changed

include/linux/netlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ struct netlink_callback {
179179
struct netlink_ext_ack *extack;
180180
u16 family;
181181
u16 min_dump_alloc;
182+
bool strict_check;
182183
unsigned int prev_seq, seq;
183184
long args[6];
184185
};

include/uapi/linux/netlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ enum nlmsgerr_attrs {
155155
#define NETLINK_LIST_MEMBERSHIPS 9
156156
#define NETLINK_CAP_ACK 10
157157
#define NETLINK_EXT_ACK 11
158+
#define NETLINK_DUMP_STRICT_CHK 12
158159

159160
struct nl_pktinfo {
160161
__u32 group;

net/netlink/af_netlink.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,13 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
17061706
nlk->flags &= ~NETLINK_F_EXT_ACK;
17071707
err = 0;
17081708
break;
1709+
case NETLINK_DUMP_STRICT_CHK:
1710+
if (val)
1711+
nlk->flags |= NETLINK_F_STRICT_CHK;
1712+
else
1713+
nlk->flags &= ~NETLINK_F_STRICT_CHK;
1714+
err = 0;
1715+
break;
17091716
default:
17101717
err = -ENOPROTOOPT;
17111718
}
@@ -1799,6 +1806,15 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
17991806
return -EFAULT;
18001807
err = 0;
18011808
break;
1809+
case NETLINK_DUMP_STRICT_CHK:
1810+
if (len < sizeof(int))
1811+
return -EINVAL;
1812+
len = sizeof(int);
1813+
val = nlk->flags & NETLINK_F_STRICT_CHK ? 1 : 0;
1814+
if (put_user(len, optlen) || put_user(val, optval))
1815+
return -EFAULT;
1816+
err = 0;
1817+
break;
18021818
default:
18031819
err = -ENOPROTOOPT;
18041820
}
@@ -2282,9 +2298,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
22822298
const struct nlmsghdr *nlh,
22832299
struct netlink_dump_control *control)
22842300
{
2301+
struct netlink_sock *nlk, *nlk2;
22852302
struct netlink_callback *cb;
22862303
struct sock *sk;
2287-
struct netlink_sock *nlk;
22882304
int ret;
22892305

22902306
refcount_inc(&skb->users);
@@ -2318,6 +2334,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
23182334
cb->min_dump_alloc = control->min_dump_alloc;
23192335
cb->skb = skb;
23202336

2337+
nlk2 = nlk_sk(NETLINK_CB(skb).sk);
2338+
cb->strict_check = !!(nlk2->flags & NETLINK_F_STRICT_CHK);
2339+
23212340
if (control->start) {
23222341
ret = control->start(cb);
23232342
if (ret)

net/netlink/af_netlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define NETLINK_F_LISTEN_ALL_NSID 0x10
1616
#define NETLINK_F_CAP_ACK 0x20
1717
#define NETLINK_F_EXT_ACK 0x40
18+
#define NETLINK_F_STRICT_CHK 0x80
1819

1920
#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
2021
#define NLGRPLONGS(x) (NLGRPSZ(x)/sizeof(unsigned long))

0 commit comments

Comments
 (0)