dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
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

      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