* [RFC v2] netlink_ack: send a capped message in case of error
@ 2015-08-25 19:43 Christophe Ricard
2015-08-25 19:43 ` [RFC v2] netlink: add NETLINK_CAP_ACK socket option Christophe Ricard
0 siblings, 1 reply; 3+ messages in thread
From: Christophe Ricard @ 2015-08-25 19:43 UTC (permalink / raw)
To: pablo, jbenc, sfeldma, sameo, davem; +Cc: netdev, Christophe Ricard
Hi,
Thanks to my first RFC proposal to cap a netlink message in case of an error, i have
rebased my work on Pablo Neira Ayuso.
After some few trials, it appears to me in_skb->sk is not the correct socket to deal with.
Here comes a reworked and tested version based on Pablo's one.
Also i believe it could be good to make it reach stable as it is somehow a bug fix.
What do you think ?
Best Regards
Christophe
Christophe Ricard (1):
netlink: add NETLINK_CAP_ACK socket option
include/uapi/linux/netlink.h | 1 +
net/netlink/af_netlink.c | 49 ++++++++++++++++++++++++++++++++------------
2 files changed, 37 insertions(+), 13 deletions(-)
--
2.1.4
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC v2] netlink: add NETLINK_CAP_ACK socket option
2015-08-25 19:43 [RFC v2] netlink_ack: send a capped message in case of error Christophe Ricard
@ 2015-08-25 19:43 ` Christophe Ricard
2015-08-26 7:46 ` Jiri Benc
0 siblings, 1 reply; 3+ messages in thread
From: Christophe Ricard @ 2015-08-25 19:43 UTC (permalink / raw)
To: pablo, jbenc, sfeldma, sameo, davem; +Cc: netdev, Christophe Ricard, stable
Since commit c05cdb1b864f ("netlink: allow large data transfers from
user-space"), the kernel may fail to allocate the necessary room for the
acknowledgment message back to userspace. This patch introduces a new
socket option that trims off the payload of the original netlink message.
The netlink message header is still included, so the user can guess from
the sequence number what is the message that has triggered the
acknowledgment.
Cc: stable@vger.kernel.org
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
include/uapi/linux/netlink.h | 1 +
net/netlink/af_netlink.c | 49 ++++++++++++++++++++++++++++++++------------
2 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index cf6a65c..6f3fe16 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -110,6 +110,7 @@ struct nlmsgerr {
#define NETLINK_TX_RING 7
#define NETLINK_LISTEN_ALL_NSID 8
#define NETLINK_LIST_MEMBERSHIPS 9
+#define NETLINK_CAP_ACK 10
struct nl_pktinfo {
__u32 group;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 67d2104..8dff29c 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -84,6 +84,7 @@ struct listeners {
#define NETLINK_F_BROADCAST_SEND_ERROR 0x4
#define NETLINK_F_RECV_NO_ENOBUFS 0x8
#define NETLINK_F_LISTEN_ALL_NSID 0x10
+#define NETLINK_F_CAP_ACK 0x20
static inline int netlink_is_kernel(struct sock *sk)
{
@@ -2258,6 +2259,13 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
nlk->flags &= ~NETLINK_F_LISTEN_ALL_NSID;
err = 0;
break;
+ case NETLINK_CAP_ACK:
+ if (val)
+ nlk->flags |= NETLINK_F_CAP_ACK;
+ else
+ nlk->flags &= ~NETLINK_F_CAP_ACK;
+ err = 0;
+ break;
default:
err = -ENOPROTOOPT;
}
@@ -2332,6 +2340,16 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
netlink_table_ungrab();
break;
}
+ case NETLINK_CAP_ACK:
+ if (len < sizeof(int))
+ return -EINVAL;
+ len = sizeof(int);
+ val = nlk->flags & NETLINK_F_CAP_ACK ? 1 : 0;
+ if (put_user(len, optlen) ||
+ put_user(val, optval))
+ return -EFAULT;
+ err = 0;
+ break;
default:
err = -ENOPROTOOPT;
}
@@ -2869,28 +2887,33 @@ EXPORT_SYMBOL(__netlink_dump_start);
void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
{
+ struct netlink_sock *nlk;
struct sk_buff *skb;
struct nlmsghdr *rep;
struct nlmsgerr *errmsg;
size_t payload = sizeof(*errmsg);
+ struct sock *sk;
- /* error messages get the original request appened */
- if (err)
+ sk = netlink_lookup(sock_net(in_skb->sk),
+ in_skb->sk->sk_protocol,
+ NETLINK_CB(in_skb).portid);
+ if (!sk)
+ return;
+
+ nlk = nlk_sk(sk);
+
+ /* Error messages get the original request appended, unless the user
+ * requests to cap the error message.
+ */
+ if (!(nlk->flags & NETLINK_F_CAP_ACK) && err)
payload += nlmsg_len(nlh);
skb = netlink_alloc_skb(in_skb->sk, nlmsg_total_size(payload),
NETLINK_CB(in_skb).portid, GFP_KERNEL);
if (!skb) {
- struct sock *sk;
-
- sk = netlink_lookup(sock_net(in_skb->sk),
- in_skb->sk->sk_protocol,
- NETLINK_CB(in_skb).portid);
- if (sk) {
- sk->sk_err = ENOBUFS;
- sk->sk_error_report(sk);
- sock_put(sk);
- }
+ sk->sk_err = ENOBUFS;
+ sk->sk_error_report(sk);
+ sock_put(sk);
return;
}
@@ -2898,7 +2921,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
NLMSG_ERROR, payload, 0);
errmsg = nlmsg_data(rep);
errmsg->error = err;
- memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh));
+ memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).portid, MSG_DONTWAIT);
}
EXPORT_SYMBOL(netlink_ack);
--
2.1.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [RFC v2] netlink: add NETLINK_CAP_ACK socket option
2015-08-25 19:43 ` [RFC v2] netlink: add NETLINK_CAP_ACK socket option Christophe Ricard
@ 2015-08-26 7:46 ` Jiri Benc
0 siblings, 0 replies; 3+ messages in thread
From: Jiri Benc @ 2015-08-26 7:46 UTC (permalink / raw)
To: Christophe Ricard
Cc: pablo, sfeldma, sameo, davem, netdev, Christophe Ricard, stable
On Tue, 25 Aug 2015 21:43:29 +0200, Christophe Ricard wrote:
> void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
> {
> + struct netlink_sock *nlk;
> struct sk_buff *skb;
> struct nlmsghdr *rep;
> struct nlmsgerr *errmsg;
> size_t payload = sizeof(*errmsg);
> + struct sock *sk;
>
> - /* error messages get the original request appened */
> - if (err)
> + sk = netlink_lookup(sock_net(in_skb->sk),
> + in_skb->sk->sk_protocol,
> + NETLINK_CB(in_skb).portid);
The necessity to look up the socket for every ack was what I didn't
like about this. Would it be possible to add a socket parameter to
various code paths that lead to netlink_ack (or a boolean, as David
suggested)? It will probably be needed to add it to
netlink_sock->netlink_rcv, netlink_kernel_cfg->input, etc.
As an alternative, David also suggested to attach the sender socket to
in_skb->sk. Could work, too.
Thanks,
Jiri
--
Jiri Benc
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-08-26 7:46 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-25 19:43 [RFC v2] netlink_ack: send a capped message in case of error Christophe Ricard
2015-08-25 19:43 ` [RFC v2] netlink: add NETLINK_CAP_ACK socket option Christophe Ricard
2015-08-26 7:46 ` Jiri Benc
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).