diff mbox series

[RFC,v2,net-next,1/3] netlink: add support for formatted extack messages

Message ID 26c2cf2e699de83905e2c21491b71af0e34d00d8.1665567166.git.ecree.xilinx@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series netlink: formatted extacks | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 5119 this patch: 5119
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang success Errors and warnings before: 1071 this patch: 1071
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 5306 this patch: 5306
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 57 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

edward.cree@amd.com Oct. 13, 2022, 9:23 a.m. UTC
From: Edward Cree <ecree.xilinx@gmail.com>

Include an 80-byte buffer in struct netlink_ext_ack that can be used
 for scnprintf()ed messages.  This does mean that the resulting string
 can't be enumerated, translated etc. in the way NL_SET_ERR_MSG() was
 designed to allow.

Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
---
 include/linux/netlink.h | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

Comments

Jakub Kicinski Oct. 13, 2022, 3:29 p.m. UTC | #1
On Thu, 13 Oct 2022 10:23:00 +0100 edward.cree@amd.com wrote:
> +	if (snprintf(__extack->_msg_buf, NETLINK_MAX_FMTMSG_LEN,	\
> +		     (fmt), ##args) >= NETLINK_MAX_FMTMSG_LEN)		\
> +		net_warn_ratelimited("truncated extack: " fmt "\n",	\
> +				     ##args);				\
> +									\

Some "take it or leave it" comments:
 - Jiri's idea of always printing may be worth exploring
 - my preference would also be to produce a warning on overflow,
   rather than the exact print, because I always worry about people
   starting to depend on the print.

   And WARN_ON() is really heavy and may trigger remediations even
   tho truncated extack is just a minor nuisance.

   I'd do:

   pr(extack formatting overflow $__FILE__:$__func__:$__LINE__ $needed_len)
   
   (I think splicing the "trunced extack:" with fmt will result
    in the format string getting stored in .ro twice?)
Johannes Berg Oct. 13, 2022, 4:16 p.m. UTC | #2
On Thu, 2022-10-13 at 08:29 -0700, Jakub Kicinski wrote:
> 
>    I'd do:
> 
>    pr(extack formatting overflow $__FILE__:$__func__:$__LINE__ $needed_len)
>    
>    (I think splicing the "trunced extack:" with fmt will result
>     in the format string getting stored in .ro twice?)
> 

If you worry about the strings (and sizes) then you probably shouldn't
advocate always having __FILE__ and __func__ ;-)

FWIW, my argument earlier was that if we have the truncated string

 a) it lets you recover better in a live system
 b) the message ought to be enough to figure out where the issue is, and
    if the message isn't unique you probably have the problem twice too

But yeah, I'm with "take it or leave it", it all doesn't matter that
much.

johannes
Jakub Kicinski Oct. 13, 2022, 4:32 p.m. UTC | #3
On Thu, 13 Oct 2022 18:16:47 +0200 Johannes Berg wrote:
> If you worry about the strings (and sizes) then you probably shouldn't
> advocate always having __FILE__ and __func__ ;-)

To be clear I meant to pass those as arguments to a common format
string. Are you saying just using them will bloat the binary?
Oh well, I guess :(
Edward Cree Oct. 17, 2022, 12:04 p.m. UTC | #4
On 13/10/2022 16:29, Jakub Kicinski wrote:
>    (I think splicing the "trunced extack:" with fmt will result
>     in the format string getting stored in .ro twice?)

Yes, it will.  I guess we could splice "%s" with fmt in _both_
 calls (snprintf and net_warn_ratelimited), pass "" to one and
 "truncated extack: " to the other.  Then there's only a single
 string to put in .ro.  Is that worth the complication?
Jakub Kicinski Oct. 17, 2022, 6:40 p.m. UTC | #5
On Mon, 17 Oct 2022 13:04:35 +0100 Edward Cree wrote:
> On 13/10/2022 16:29, Jakub Kicinski wrote:
> >    (I think splicing the "trunced extack:" with fmt will result
> >     in the format string getting stored in .ro twice?)  
> 
> Yes, it will.  I guess we could splice "%s" with fmt in _both_
>  calls (snprintf and net_warn_ratelimited), pass "" to one and
>  "truncated extack: " to the other.  Then there's only a single
>  string to put in .ro.  Is that worth the complication?

I vote 'yes', with a simple comment next to it, it should be a fairly
obvious trick to a reader of this code.
diff mbox series

Patch

diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index d51e041d2242..4cbe87739c4d 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -64,6 +64,7 @@  netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
 
 /* this can be increased when necessary - don't expose to userland */
 #define NETLINK_MAX_COOKIE_LEN	20
+#define NETLINK_MAX_FMTMSG_LEN	80
 
 /**
  * struct netlink_ext_ack - netlink extended ACK report struct
@@ -75,6 +76,8 @@  netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
  * @miss_nest: nest missing an attribute (%NULL if missing top level attr)
  * @cookie: cookie data to return to userspace (for success)
  * @cookie_len: actual cookie data length
+ * @_msg_buf: output buffer for formatted message strings - don't access
+ *	directly, use %NL_SET_ERR_MSG_FMT
  */
 struct netlink_ext_ack {
 	const char *_msg;
@@ -84,13 +87,13 @@  struct netlink_ext_ack {
 	u16 miss_type;
 	u8 cookie[NETLINK_MAX_COOKIE_LEN];
 	u8 cookie_len;
+	char _msg_buf[NETLINK_MAX_FMTMSG_LEN];
 };
 
 /* Always use this macro, this allows later putting the
  * message into a separate section or such for things
  * like translation or listing all possible messages.
- * Currently string formatting is not supported (due
- * to the lack of an output buffer.)
+ * If string formatting is needed use NL_SET_ERR_MSG_FMT.
  */
 #define NL_SET_ERR_MSG(extack, msg) do {		\
 	static const char __msg[] = msg;		\
@@ -102,9 +105,27 @@  struct netlink_ext_ack {
 		__extack->_msg = __msg;			\
 } while (0)
 
+#define NL_SET_ERR_MSG_FMT(extack, fmt, args...) do {			\
+	struct netlink_ext_ack *__extack = (extack);			\
+									\
+	if (!__extack)							\
+		break;							\
+	if (snprintf(__extack->_msg_buf, NETLINK_MAX_FMTMSG_LEN,	\
+		     (fmt), ##args) >= NETLINK_MAX_FMTMSG_LEN)		\
+		net_warn_ratelimited("truncated extack: " fmt "\n",	\
+				     ##args);				\
+									\
+	do_trace_netlink_extack(__extack->_msg_buf);			\
+									\
+	__extack->_msg = __extack->_msg_buf;				\
+} while (0)
+
 #define NL_SET_ERR_MSG_MOD(extack, msg)			\
 	NL_SET_ERR_MSG((extack), KBUILD_MODNAME ": " msg)
 
+#define NL_SET_ERR_MSG_FMT_MOD(extack, fmt, args...)	\
+	NL_SET_ERR_MSG_FMT((extack), KBUILD_MODNAME ": " fmt, ##args)
+
 #define NL_SET_BAD_ATTR_POLICY(extack, attr, pol) do {	\
 	if ((extack)) {					\
 		(extack)->bad_attr = (attr);		\