|
@@ -1706,6 +1706,13 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
|
|
|
nlk->flags &= ~NETLINK_F_EXT_ACK;
|
|
|
err = 0;
|
|
|
break;
|
|
|
+ case NETLINK_DUMP_STRICT_CHK:
|
|
|
+ if (val)
|
|
|
+ nlk->flags |= NETLINK_F_STRICT_CHK;
|
|
|
+ else
|
|
|
+ nlk->flags &= ~NETLINK_F_STRICT_CHK;
|
|
|
+ err = 0;
|
|
|
+ break;
|
|
|
default:
|
|
|
err = -ENOPROTOOPT;
|
|
|
}
|
|
@@ -1799,6 +1806,15 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
|
|
|
return -EFAULT;
|
|
|
err = 0;
|
|
|
break;
|
|
|
+ case NETLINK_DUMP_STRICT_CHK:
|
|
|
+ if (len < sizeof(int))
|
|
|
+ return -EINVAL;
|
|
|
+ len = sizeof(int);
|
|
|
+ val = nlk->flags & NETLINK_F_STRICT_CHK ? 1 : 0;
|
|
|
+ if (put_user(len, optlen) || put_user(val, optval))
|
|
|
+ return -EFAULT;
|
|
|
+ err = 0;
|
|
|
+ break;
|
|
|
default:
|
|
|
err = -ENOPROTOOPT;
|
|
|
}
|
|
@@ -2282,9 +2298,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
|
|
|
const struct nlmsghdr *nlh,
|
|
|
struct netlink_dump_control *control)
|
|
|
{
|
|
|
+ struct netlink_sock *nlk, *nlk2;
|
|
|
struct netlink_callback *cb;
|
|
|
struct sock *sk;
|
|
|
- struct netlink_sock *nlk;
|
|
|
int ret;
|
|
|
|
|
|
refcount_inc(&skb->users);
|
|
@@ -2318,6 +2334,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
|
|
|
cb->min_dump_alloc = control->min_dump_alloc;
|
|
|
cb->skb = skb;
|
|
|
|
|
|
+ nlk2 = nlk_sk(NETLINK_CB(skb).sk);
|
|
|
+ cb->strict_check = !!(nlk2->flags & NETLINK_F_STRICT_CHK);
|
|
|
+
|
|
|
if (control->start) {
|
|
|
ret = control->start(cb);
|
|
|
if (ret)
|