Message ID | 20240912024018.8117-1-atlas.yu@canonical.com (mailing list archive) |
---|---|
State | Rejected |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net,v1] netlink: optimize the NMLSG_OK macro | expand |
From: Atlas Yu <atlas.yu@canonical.com> Date: Thu, 12 Sep 2024 10:40:18 +0800 > When nlmsg_len >= sizeof(hdr) and nlmsg_len <= len are true, we can set > up an inequation: len >= nlmsg_len >= sizeof(hdr), which makes checking > len >= sizeof(hdr) useless. > > gcc -O3 cannot optimize ok1 to generate the same instructions as ok2 on > x86_64 (not investigated on other architectures). > int ok1(int a, int b, int c) { return a >= b && c >= b && c <= a; } > int ok2(int a, int b, int c) { return c >= b && c <= a; } > > Signed-off-by: Atlas Yu <atlas.yu@canonical.com> > --- > include/uapi/linux/netlink.h | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h > index f87aaf28a649..85dcfa6b33af 100644 > --- a/include/uapi/linux/netlink.h > +++ b/include/uapi/linux/netlink.h > @@ -104,8 +104,7 @@ struct nlmsghdr { > #define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ > (struct nlmsghdr *)(((char *)(nlh)) + \ > NLMSG_ALIGN((nlh)->nlmsg_len))) > -#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ > - (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ > +#define NLMSG_OK(nlh,len) ((nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ If len < sizeof(struct nlmsghdr) (more specifically, offsetof(struct nlmsghdr, nlmsg_len)), you can't access nlmsg_len; it returns a garbage. > (nlh)->nlmsg_len <= (len)) > #define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) > > -- > 2.43.0 >
diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h index f87aaf28a649..85dcfa6b33af 100644 --- a/include/uapi/linux/netlink.h +++ b/include/uapi/linux/netlink.h @@ -104,8 +104,7 @@ struct nlmsghdr { #define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ (struct nlmsghdr *)(((char *)(nlh)) + \ NLMSG_ALIGN((nlh)->nlmsg_len))) -#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ - (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ +#define NLMSG_OK(nlh,len) ((nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ (nlh)->nlmsg_len <= (len)) #define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
When nlmsg_len >= sizeof(hdr) and nlmsg_len <= len are true, we can set up an inequation: len >= nlmsg_len >= sizeof(hdr), which makes checking len >= sizeof(hdr) useless. gcc -O3 cannot optimize ok1 to generate the same instructions as ok2 on x86_64 (not investigated on other architectures). int ok1(int a, int b, int c) { return a >= b && c >= b && c <= a; } int ok2(int a, int b, int c) { return c >= b && c <= a; } Signed-off-by: Atlas Yu <atlas.yu@canonical.com> --- include/uapi/linux/netlink.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)