From: Jani Nikula <jani.nikula@linux.intel.com>
To: Daniel Vetter <daniel@ffwll.ch>, Dmitry Malkin <DMalkin@ptsecurity.com>
Cc: "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>
Subject: Re: [DRM] drm_get_connector_name internal static string buffer causes a race
Date: Tue, 25 Mar 2014 12:44:02 +0200 [thread overview]
Message-ID: <87k3biimml.fsf@intel.com> (raw)
In-Reply-To: <20140324203132.GK26878@phenom.ffwll.local>
On Mon, 24 Mar 2014, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Mon, Mar 24, 2014 at 12:06:21PM +0000, Dmitry Malkin wrote:
>>
>> Hello guys,
>>
>> I've been playing with reloading intel gfx driver (i915) in a cycle,
>> for a while, and at some point I've found a non-deterministic kernel
>> crash with a highly-variable iteration dependency -- 2 to 200 driver
>> reload iterations.
>>
>> The apparent race is over the shared internal string buffer in
>> drm_get_connector_name(). It is mostly harmless, due to its results
>> being mostly used for log output, but in at least one case --
>> drm_sysfs_connector_add() -- this leads to a more critical error.
>>
>> Race scenario:
>>
>> - drm_sysfs_connector_add()
>> - drm_get_connector_name()
>> vs.
>> - anything that generates log messages involving DRM connectors
>> - drm_get_connector_name()
>>
>> (and many other from drm_crtc.c) shares with caller const char* to
>> internal static char buffer. If something call it from other thread,
>> while main thread strore and use returned pointer it may overwrite
>> connector name.
>>
>> Here are we go: registering HDMI connecter (drm_sysfs_connector_add
>> store and use pointer from drm_get_connector_name) and the same time
>> got VGA connector name down through the stack. (the second thread is
>> upowerd who watch continuously sysfs)
>
> Yeah, in my recent kerneldoc series I've noticed this too and added FIXME
> comments. There's a lot more than just those you've pointed out. The
> problem is that fixing these will be an awful lot of work since you need
> to add proper cleanup code (calling kfree()) to all the required places.
>
> So a full subsystem wide code audit for every single use-site of these.
It would be much easier and much much less error prone to add a name
field (either a fixed size or kmalloced buffer) in drm_connector and
drm_encoder structs, and initialize them in connector/encoder
init. AFAICT the name does not change during the objects' lifetime. None
of the use-sites would need to be changed.
The question is whether (number of connectors + number of encoders) * 32
bytes is too high a price to pay for the implementation simplicity. I
think not.
Another alternative to returning kmalloced strings is:
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 16ca28ed5ee8..85c8ed191daa 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -277,11 +277,10 @@ EXPORT_SYMBOL(drm_get_encoder_name);
*
* FIXME: This isn't really multithreading safe.
*/
-const char *drm_get_connector_name(const struct drm_connector *connector)
+const char *drm_get_connector_name(char *buf, size_t bufsize,
+ const struct drm_connector *connector)
{
- static char buf[32];
-
- snprintf(buf, 32, "%s-%d",
+ snprintf(buf, bufsize, "%s-%d",
drm_connector_enum_list[connector->connector_type].name,
connector->connector_type_id);
return buf;
So the callers may use the kind of buffers they want. Something like
this may be needed for drm_get_format_name() anyway.
BR,
Jani.
--
Jani Nikula, Intel Open Source Technology Center
prev parent reply other threads:[~2014-03-25 10:43 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-24 12:06 [DRM] drm_get_connector_name internal static string buffer causes a race Dmitry Malkin
2014-03-24 20:31 ` Daniel Vetter
2014-03-25 8:08 ` Dmitry Malkin
2014-03-25 10:43 ` Daniel Vetter
2014-03-25 11:23 ` Dmitry Malkin
2014-03-25 12:36 ` Daniel Vetter
2014-03-25 10:44 ` Jani Nikula [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87k3biimml.fsf@intel.com \
--to=jani.nikula@linux.intel.com \
--cc=DMalkin@ptsecurity.com \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox