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] [thread-next>] [day] [month] [year] [list]
Date:	Sun, 15 Feb 2009 20:35:23 +0100
From:	Frederic Weisbecker <fweisbec@...il.com>
To:	Sitsofe Wheeler <sitsofe@...oo.com>
Cc:	Ingo Molnar <mingo@...e.hu>,
	Andrew Morton <akpm@...ux-foundation.org>,
	linux-kernel@...r.kernel.org, Rusty Russell <rusty@...tcorp.com.au>
Subject: Re: Poking ieee80211_default_rc_algo causes kernel lockups

On Sun, Feb 15, 2009 at 04:09:57PM +0000, Sitsofe Wheeler wrote:
> Hi,
> 
> As mentioned on
> http://groups.google.com/group/fa.linux.kernel/browse_frm/thread/d4a6ce26360613fa/b362792a2debced6?#b362792a2debced6
> , poking /sys/module/mac80211/parameters/ieee80211_default_rc_algo and
> then trying to read values back is currently causing the kernel to go
> funny. E.g.
> echo blah > /sys/module/mac80211/parameters/ieee80211_default_rc_algo
> cat /sys/module/mac80211/parameters/ieee80211_default_rc_algo
> 
> Causes 2.6.29rc5 on my EeePC 900 to lock up.
> 
> -- 
> Sitsofe
> 


On Sun, Feb 15, 2009 at 04:09:57PM +0000, Sitsofe Wheeler wrote:
> Hi,
> 
> As mentioned on
> http://groups.google.com/group/fa.linux.kernel/browse_frm/thread/d4a6ce26360613fa/b362792a2debced6?#b362792a2debced6
> , poking /sys/module/mac80211/parameters/ieee80211_default_rc_algo and
> then trying to read values back is currently causing the kernel to go
> funny. E.g.
> echo blah > /sys/module/mac80211/parameters/ieee80211_default_rc_algo
> cat /sys/module/mac80211/parameters/ieee80211_default_rc_algo
> 
> Causes 2.6.29rc5 on my EeePC 900 to lock up.
> 

I think I've found something:

When you set a new value to a module parameter through
sysfs, here is what happens (traced with the function_graph_tracer,
I've zapped a lot of entries to keep it clear)


 1)               |  sys_open() {
 1)               |            sysfs_open_file() {
 1)               |              kmem_cache_alloc() {
 1)   0.609 us    |                __might_sleep();
 1)   2.046 us    |              }
 1) + 58.976 us   |            }
 1) ! 471.823 us  |  }


The file is opened here, and sysfs will allocate a private buffer for this
file...


 1)               |  sys_write() {
 1)               |    vfs_write() {
 1)               |      sysfs_write_file() {
 1) + 26.446 us   |        get_zeroed_page();
 1)   0.789 us    |        sysfs_get_active_two();
 1)               |        module_attr_store() {
 1)               |          param_attr_store() {
 1)   5.625 us    |            param_set_charp();
 1)   7.279 us    |          }
 1)   8.919 us    |        }
 1)   4.113 us    |      }
 1) + 62.502 us   |    }
 1) + 64.961 us   |  }

Then we go to write the file, the buffer we allocated is used to store what
the user gave us as the new value of the module parameter.

This filled buffer is relayed to the module parameter and the address of the buffer
is directly assigned to the pointer of the module parameter:

int param_set_charp(const char *val, struct kernel_param *kp)
{
	[...]
	*(char **)kp->arg = (char *)val;
	return 0;
}

At this stage, all is good.

But just after we close the file:


 1)               |            sysfs_release() {
 1)               |              kfree() {
 1)   1.105 us    |                __phys_addr();
 1)   2.842 us    |              }
 1)               |              free_pages() {
 1)   0.609 us    |                __phys_addr();
 1)               |                __free_pages() {
 1)               |                  free_hot_page() {
 1)               |                    free_hot_cold_page() {
 1)   1.113 us    |                      get_pageblock_flags_group();
 1)   3.061 us    |                    }
 1)   4.466 us    |                  }
 1)   5.744 us    |                }
 1)   8.166 us    |              }
 1)               |              kfree() {
 1)   0.601 us    |                __phys_addr();
 1)   2.052 us    |              }
 1) + 18.686 us   |            }

The buffer we just assigned to the module parameter is freed. So we can't reuse it later,
but that's what is done later when we read it, since this bad address is dereferenced:

int param_get_charp(char *buffer, struct kernel_param *kp)
{
	return sprintf(buffer, "%s", *((char **)kp->arg));
}

So the problem seems not related to mac80211 but actually to module parameter management.
I'm not sure what is the right fix.

I guess we should use the following field in struct kernel_param:
struct kparam_string *str;

But this implies that string module params must not be simply pointers but static arrays.
Although I find it a bit insane to modify a string parameter at runtime.

The string is parsed by a module on load but not after, so a callback given by the module
seems to me more sane...


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ