lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250422104456.6fcca401@collabora.com>
Date: Tue, 22 Apr 2025 10:44:56 +0200
From: Boris Brezillon <boris.brezillon@...labora.com>
To: Adrián Larumbe <adrian.larumbe@...labora.com>
Cc: linux-kernel@...r.kernel.org, dri-devel@...ts.freedesktop.org,
 kernel@...labora.com, Liviu Dudau <liviu.dudau@....com>, Steven Price
 <steven.price@....com>, Maarten Lankhorst
 <maarten.lankhorst@...ux.intel.com>, Maxime Ripard <mripard@...nel.org>,
 Thomas Zimmermann <tzimmermann@...e.de>, David Airlie <airlied@...il.com>,
 Simona Vetter <simona@...ll.ch>, Sumit Semwal <sumit.semwal@...aro.org>,
 Christian König <christian.koenig@....com>,
 linux-media@...r.kernel.org, linaro-mm-sig@...ts.linaro.org
Subject: Re: [PATCH v9 4/4] drm/panthor: show device-wide list of DRM GEM
 objects over DebugFS

On Fri, 18 Apr 2025 21:15:32 +0100
Adrián Larumbe <adrian.larumbe@...labora.com> wrote:

> Hi Boris,
> 
> On 18.04.2025 10:04, Boris Brezillon wrote:
> > On Fri, 18 Apr 2025 03:27:07 +0100
> > Adrián Larumbe <adrian.larumbe@...labora.com> wrote:
> >  
> > > +#ifdef CONFIG_DEBUG_FS
> > > +static void
> > > +panthor_gem_debugfs_format_flags(char flags_str[], int flags_len,
> > > +				 const char * const names[], u32 name_count,
> > > +				 u32 flags)
> > > +{
> > > +	bool first = true;
> > > +	int offset = 0;
> > > +
> > > +#define ACC_FLAGS(...) \
> > > +	({ \
> > > +		offset += snprintf(flags_str + offset, flags_len - offset, ##__VA_ARGS__); \
> > > +		if (offset == flags_len) \
> > > +			return; \
> > > +	})  
> >
> > I tried applying, but checkpatch complains with:
> >
> > -:225: WARNING:MACRO_WITH_FLOW_CONTROL: Macros with flow control statements should be avoided
> > #225: FILE: drivers/gpu/drm/panthor/panthor_gem.c:359:
> > +#define ACC_FLAGS(...) \
> > +	({ \
> > +		offset += snprintf(flags_str + offset, flags_len - offset, ##__VA_ARGS__); \
> > +		if (offset == flags_len) \
> > +			return; \
> > +	})
> >
> >
> > and now I'm wondering why we even need to return early? Oh, and the
> > check looks suspicious to: snprintf() returns the number of chars
> > that would have been written if the destination was big enough, so
> > the offset will actually be greater than flags_len if the formatted
> > string doesn't fit.  
> 
> I noticed this warning when running checkpatch myself, and while a return isn't strictly
> necessary, I thought there was no point in going down the function when no more bytes
> could be written into the format string because it's already full.
> 
> I did check the code for other locations where flow control is happening inside a macro
> and found this:
> 
> #define group_queue_work(group, wname) \
> 	do { \
> 		group_get(group); \
> 		if (!queue_work((group)->ptdev->scheduler->wq, &(group)->wname ## _work)) \
> 			group_put(group); \
> 	} while (0)
> 
> although I'm not sure whether the do {} while (0) is right there to make the warning go away.

No, the main difference is that it doesn't return behind the callers'
back which is what checkscript is complaining about, though using do {}
while(0) is usually preferred over ({}) when
you have nothing to return.

> 
> > snprintf() returns the number of chars
> > that would have been written if the destination was big enough, so
> > the offset will actually be greater than flags_len if the formatted
> > string doesn't fit.  
> 
> Good catch, I don't know why I thought snprintf() would print at most 'flags_len
> - offset' bytes, and would return exactly that count at most too, rather than
> throwing a hypothetical max value. Then maybe checking whether 'if (offset >=
> flags_len)' would be enough ?

It should.

> 
> 
> > There are a few other formatting issues reported by checkpatch
> > --strict BTW.
> >
> > Unfortunately this led me to have a second look at these bits
> > and I have a few more comments, sorry about that :-/.  
> 
> > +
> > +	ACC_FLAGS("%c", '(');  
> 
> > Now that flags have their own columns, I'm not sure it makes sense
> > surround them with parenthesis. That's even weird if we start running
> > out of space, because there would be an open '(', a few flags,
> > the last one being truncated, and no closing ')'. The other thing
> > that's bothering me is the fact we don't know when not all flags
> > have been displayed because of lack of space.
> >  
> > > +
> > > +	if (!flags)
> > > +		ACC_FLAGS("%s", "none");
> > > +
> > > +	while (flags) {
> > > +		u32 bit = fls(flags) - 1;  
> >
> > I would probably print flags in bit position order, so ffs()
> > instead of fls().
> >  
> > > +		u32 idx = bit + 1;  
> >
> > Why do you have a "+ 1" here? Feels like an off-by-one error to
> > me.
> >  
> > > +
> > > +		if (!first)
> > > +			ACC_FLAGS("%s", ",");
> > > +
> > > +		if (idx < name_count && names[idx])
> > > +			ACC_FLAGS("%s", names[idx]);
> > > +
> > > +		first = false;
> > > +		flags &= ~BIT(bit);
> > > +	}
> > > +
> > > +	ACC_FLAGS("%c", ')');
> > > +
> > > +#undef ACC_FLAGS
> > > +}  
> >
> > How about something like that:
> >
> > static void
> > panthor_gem_debugfs_format_flags(char *flags_str, u32 flags_str_len,
> >                                  const char * const flag_names[],
> >                                  u32 flag_name_count, u32 flags)
> > {
> > 	int offset = 0;
> >
> > 	if (!flags) {
> >         	snprintf(flags_str, flags_str_len, "%s", "none");
> > 		return;
> > 	}
> >
> > 	while (flags) {
> > 		const char *flag_name = "?";
> > 		u32 flag = ffs(flags) - 1;
> > 		int new_offset = offset;
> >
> > 		flags &= ~BIT(flag);
> >
> > 		if (flag < flag_name_count && flag_names[flag])
> > 			flag_name = flag_names[flag];
> >
> > 		/* Print as much as we can. */
> > 		new_offset += snprintf(flags_str + offset, flags_str_len - offset,
> > 				       "%s%s", offset ? "," : "", flag_name);
> >
> > 		/* If we have flags remaining, check that we have enough space for
> > 		 * the "...".
> > 		 */
> > 		if (flags)
> > 			new_offset += strlen(",...");
> >
> > 		/* If we overflowed, replace what we've written by "..." and
> > 		 * bail out.
> > 		 */
> > 		if (new_offset > flags_str_len) {
> > 			snprintf(flags_str + offset, flags_str_len - offset,
> > 				 "%s...", offset ? "," : "");
> > 			return;
> > 		}
> >
> > 		offset = new_offset;
> >         }
> > }  
> 
> This looks good to me. However, I'm starting to wonder whether it makes sense to
> try to come up with a very elaborate flag formatting scheme, because of two
> reasons:
> 
> - It messes up with the output because we need to provide enough headroom in
> case the flag set will increase in the future. This is not a big deal because
> the debugfs file is meant to be parsed by UM tools, but ...
> 
> - In case we go over the space available to print flags, not printing the
> remaining ones feels even less informative than printing let's say a hexadecimal
> mask, because parsing tools would rather deal with no missing data than the
> absence of human-readable flag names.
> 
> On top of that, I think, while these flags could be mostly of interest to parsing
> tools, they'd be less so to someone casually peeking into the raw textual
> output. I think they'd be mostly interested in the process which triggered
> their creation, their size, virtual address in the VM, and above all their name
> (potentially a very long one).
> 
> With all these things born in mind, I'd say we'd best just print a 32 bit mask
> for both flag fields, for which we'd always know the exact span in bytes, and
> then print all the available flag names in the debugfs file prelude for parsing
> tools to pick up on.

Yeah, I think I agree with you. The flag printing is messy as it is,
and if we're going to use a tool to parse the output, we're probably
better off with an hexadecimal value here.

Regards,

Boris

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ