I am reasonably new to sysfs with respect to driver development and I seem to be observing some rather odd behavior. To make a long story short, it seems that the kernel is not passing back complete structs to my callback. This driver is a rather simple SPI-ADC driver that is being used to read analog thermal / voltage data.
Now, I have a hard time believing that I just found a bug in the Linux kernel in such a widely-used subsystem. I have scoured the internet for anything that might help, but all signs indicate that this should work as is. Other passed structures seem to be populated correctly, it is only the attr->attr member that appears to be NULL.
I should also mention that this is against the 3.2 kernel.
So, in short, what would causes sysfs callbacks to not receive a fully populated kobj_attribute struct?
Sample Code:
static ssize_t ads7960_sysfs_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
int var, rc, i = 0, j = 0;
long channel = 0;
//DEBUG
printk("%s: kobj->name = %s\n", __func__, kobj->name);
printk("%s: attr = %p\n", __func__, attr);
printk("%s: attr->attr = %p\n", __func__, attr->attr);
printk("%s: attr->attr.name = %s\n", __func__, attr->attr.name);
printk("%s: attr->attr.mode = %o\n", __func__, attr->attr.mode);
/* check for silly things */
if ((attr->attr.name == NULL) || (strlen(attr->attr.name) < 1)) {
printk("%s: invalid channel number. = %s\n", __func__, attr->attr.name);
return -EINVAL;
}
... snip (We never get past here) ...
static struct kobj_attribute ads7960_ch0 = __ATTR(0, 0444, ads7960_sysfs_show, NULL);
static struct kobj_attribute ads7960_ch1 = __ATTR(1, 0444, ads7960_sysfs_show, NULL);
static struct kobj_attribute ads7960_ch2 = __ATTR(2, 0444, ads7960_sysfs_show, NULL);
... snip (there are 12 total ADC channels in the same format) ...
static struct attribute *ch_attrs[] = {
&ads7960_ch0.attr,
&ads7960_ch1.attr,
&ads7960_ch2.attr,
... snip (same 12 channels as above)...
NULL,
};
static struct attribute_group attr_group = {
.attrs = ch_attrs,
};
static struct attribute_group *attr_group_ptr = &attr_group;
... snip ...
static struct spi_driver ads7960_driver = {
.driver = {
.name = "ads7960",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.groups = &attr_group_ptr,
},
.probe = ads7960_probe,
.remove = __devexit_p(ads7960_remove),
.id_table = ads7960_id,
};
... snip ...
Output Produced:
[root#172.17.152.42: ]# cat /sys/bus/spi/drivers/ads7960/4
[ 65.344789] ads7960_sysfs_show: kobj->name = ads7960
[ 65.350026] ads7960_sysfs_show: attr = dc934000
[ 65.354859] ads7960_sysfs_show: attr->attr = (null)
[ 65.360155] ads7960_sysfs_show: attr->attr.name = (null)
[ 65.365746] ads7960_sysfs_show: attr->attr.mode = 0
[ 65.370861] ads7960_sysfs_show: invalid channel number. = (null)
cat: read error: Invalid argument
References
http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/samples/kobject/kobject-example.c
http://kroah.com/log/blog/2013/06/26/how-to-create-a-sysfs-file-correctly/
Edit 1:
To summarize the comments below, I manually called sysfs_create_group from my _init and the kobj_attribute struct passed to the callback appeared to be correctly populated. The callback now works without issue (or modification, for that matter). As was stated below, spi_register_driver just calls sysfs_create_group. So, why would one invoke the callback properly while the other does not?
Per comments below, below is the complete _init function and spi_driver structure. The test that I did to manually create the paths myself was based off the _init code in the first reference with almost no modification.
static struct spi_driver ads7960_driver = {
.driver = {
.name = "ads7960",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.groups = attr_groups,
},
.probe = ads7960_probe,
.remove = __devexit_p(ads7960_remove),
.id_table = ads7960_id,
};
static int __init ads7960_init(void)
{
return spi_register_driver(&ads7960_driver);
}
module_init(ads7960_init);
The .groups member of struct device_driver must point to a NULL-terminated list of pointers to attribute groups, not to a single pointer to an attribute group. So, instead of attr_group_ptr, you need:
static struct attribute_group *attr_groups[] = { &attr_group, NULL };
...and then
static struct spi_driver ads7960_driver = {
.driver = {
.name = "ads7960",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.groups = attr_groups,
},
However, there's a helper macro to declare both the attribute group and list of attribute groups that you can use instead:
static struct attribute *ch_attrs[] = {
&ads7960_ch0.attr,
&ads7960_ch1.attr,
&ads7960_ch2.attr,
/* ... */
NULL,
};
ATTRIBUTE_GROUPS(ch); /* declares ch_group and ch_groups */
static struct spi_driver ads7960_driver = {
.driver = {
.name = "ads7960",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.groups = ch_groups,
},
Related
void xbee_init(struct net_device *dev)
{
struct xbee_priv *priv;
dev->netdev_ops->ndo_set_mac_address = xbee_mac_addr;
dev->netdev_ops->ndo_validate_addr = xbee_validate_addr;
dev->mtu = XBEE_DATA_MTU;
dev->addr_len = 8;
dev->tx_queue_len = 1000;
memset(dev->broadcast, 0xFF, 8);
dev->netdev_ops->ndo_open = xbee_open;
dev->netdev_ops->ndo_stop = xbee_release;
dev->hard_start_xmit = xbee_tx;
dev->netdev_ops->ndo_do_ioctl = xbee_ioctl;
dev->get_stats = xbee_stats;
Even when I make my own structure like this :
static const struct net_device_ops xbee_ops = {
.ndo_open = xbee_open,
.ndo_stop = xbee_close,
.ndo_start_xmit = xbee_xmit,
.ndo_do_ioctl = xbee_ioctl,
.ndo_set_mac_address = xbee_mac_addr,
} ;
dev->netdev_ops = &xbee_ops;
It shows me this error :
assignment of member ‘ndo_set_mac_address’ in read-only object
dev->netdev_ops->ndo_set_mac_address = xbee_mac_addr;
Your own struct does not help because it is not part of the problem.
If you look at the definition of struct net_device you can see this:
const struct net_device_ops *netdev_ops;
This means, the memory where dev->netdev_ops is pointing to, is const.
Therefore you cannot modify dev->netdev_ops->ndo_set_mac_address or any other member.
You need to prepare your variable xbee_ops completely before you assign it to dev->netdev_ops.
I'm trying to see how I can get a loaded module image name from an arbitrary address from the kernel code.
In user mode I would do this:
void* pAddr;
VOID* pBase;
WCHAR buff[MAX_PATH] = {0};
//Get address of some function in some module (just to test it)
pAddr = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetCurrentProcess");
//Get module base address
RtlPcToFileHeader(pAddr, &pBase);
//Get module image file name
GetModuleFileNameEx(GetCurrentProcess(), (HMODULE)pBase, buff, SIZEOF(buff));
Is there a way to do the same in kernel mode if I have pAddr that can point to some address in kernel or user space?
EDIT: While waiting for the answer I came up with my own code (using undocumented way of traversing PEB):
#ifdef CALLING_FROM_KERNEL_MODE
//Kernel mode
TEB* pTEB = (TEB*)PsGetCurrentThreadTeb();
#else
//User mode
#if defined(_M_X64)
//64-bit
TEB* pTEB = reinterpret_cast<TEB*>(__readgsqword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#else
//32-bit
TEB* pTEB = reinterpret_cast<TEB*>(__readfsdword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#endif
#endif
PEB* p_PEB = pTEB->ProcessEnvironmentBlock;
PEB_LDR_DATA* pPLD = p_PEB->Ldr;
const WCHAR* pModName = NULL;
LIST_ENTRY* pLE = &pPLD->InMemoryOrderModuleList;
LIST_ENTRY* pLE_Head = pLE;
while(pLE_Head != pLE->Flink)
{
PLDR_DATA_TABLE_ENTRY pLDTE = CONTAINING_RECORD(pLE, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
size_t szcbSizeOfImg = (size_t)pLDTE->Reserved3[1];
if((size_t)pAddr - (size_t)pLDTE->DllBase < szcbSizeOfImg)
{
pModName = pLDTE->FullDllName.Buffer;
break;
}
pLE = pLE->Flink;
}
The problem is that although it works from a user-mode, from a kernel mode PsGetCurrentThreadTeb() seems to return NULL. Does this mean kernel threads do not have a TEB?
this can be done by creating list of all loaded modules via ZwQuerySystemInformation with SystemModuleInformation
void fgt(PVOID *Callers, ULONG Count)
{
NTSTATUS status;
ULONG cb = 0x10000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PRTL_PROCESS_MODULES prpm = (PRTL_PROCESS_MODULES)ExAllocatePool(PagedPool, cb))
{
if (0 <= (status = NtQuerySystemInformation(SystemModuleInformation, prpm, cb, &cb)))
{
do
{
PVOID Caller = *Callers++;
if (ULONG NumberOfModules = prpm->NumberOfModules)
{
PRTL_PROCESS_MODULE_INFORMATION Modules = prpm->Modules;
do
{
if ((SIZE_T)Caller - (SIZE_T)Modules->ImageBase < Modules->ImageSize)
{
DbgPrint("%p> %s\n", Caller, Modules->FullPathName);
break;
}
} while (Modules++, --NumberOfModules);
}
} while (--Count);
}
ExFreePool(prpm);
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
}
I've a function I wrote in order to run a given function on all processors. It works perfectly well in all cases except the following case:
When I try to use it within a kprobe that I registered.
Here's some code:
static DEFINE_MUTEX(entryMutex);
static struct kretprobe my_kprobe = {
.entry_handler = (kprobe_opcode_t *) NULL,
.handler = (kprobe_opcode_t *) process_entry_callback,
.maxactive = 1000,
.data_size = 0
};
static int driver_init(void)
{
my_kprobe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("sys_execve");
if ((ret = register_kretprobe(&my_kprobe)) < 0)
return -1;
return 0;
}
void foo(void* nothing)
{
printk("In foo\n");
}
static int process_entry_callback(struct kretprobe_instance* instance, struct pt_regs* regs)
{
mutex_lock(&entryMutex);
for(int i = 0; i < 4; ++i) // assumes there are 4 processors
run_func(foo, NULL, i);
mutex_unlock(&entryMutex);
return 0;
}
void run_func_wrap(struct function_data* data)
{
data->func(data->context);
wake_up_process(data->waiting_task);
*(data->condition) = TRUE;
}
void run_func(SCHEDULED_FUNC func, void *context, int processor)
{
struct function_data data;
struct task_struct* th;
BOOLEAN condition = FALSE;
wait_queue_head_t queue;
init_waitqueue_head(&queue);
data.func = func;
data.waiting_task = current;
data.context = context;
data.condition = &condition;
th = kthread_create(sched_func_wrap, &data, "th");
kthread_bind(th, processor);
wake_up_process(th);
wait_event(queue, condition);
}
F
After the call to 'run_func' in process_entry_callback I can no longer run any programs. Every time I start a new program it just stuck. After a while I get 'processor lockup' warning in the system log.
I suspect that it has something to do with the IRQ levels.
Any suggestions ?
EDIT:
It also happens when using the following function:
smp_call_function_single
which can be found in smp.c # the Linux kernel source code.
instead of my function:
run_func
I am trying to create a flume-thrift client in c (c_glib) but have trouble creating the gobject that shall be sent to the server. I get the following error at the line in main.c:
`GLib-GObject-WARNING **: IA__g_object_new_valist: object class `ThriftFlumeEventType' has no property named `timestamp'`
The code in flume_types.h and flume_types.c is autogenerated from thrift. Tell me if you need to see more code. I am thankful for all the help I can get!
Parts of the code in flume_types.h:
struct _ThriftFlumeEvent
{
ThriftStruct parent;
/* public */
gint64 timestamp;
gboolean __isset_timestamp;
Priority priority;
gboolean __isset_priority;
GByteArray * body;
gboolean __isset_body;
gint64 nanos;
gboolean __isset_nanos;
gchar * host;
gboolean __isset_host;
GHashTable * fields;
gboolean __isset_fields;
};
typedef struct _ThriftFlumeEvent ThriftFlumeEvent;
GType thrift_flume_event_get_type (void);
#define TYPE_THRIFT_FLUME_EVENT (thrift_flume_event_get_type())
Parts of the code in flume_types.c:
void
thrift_flume_event_instance_init (ThriftFlumeEvent * object)
{
printf("thrift_flume_event_instance_init");
/* satisfy -Wall */
THRIFT_UNUSED_VAR (object);
object->timestamp = 0;
object->__isset_timestamp = FALSE;
object->__isset_priority = FALSE;
object->body = NULL;
object->__isset_body = FALSE;
object->nanos = 0;
object->__isset_nanos = FALSE;
object->host = NULL;
object->__isset_host = FALSE;
object->fields = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
object->__isset_fields = FALSE;
}
GType
thrift_flume_event_get_type (void)
{
static GType type = 0;
if (type == 0)
{
static const GTypeInfo type_info =
{
sizeof (ThriftFlumeEventClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) thrift_flume_event_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (ThriftFlumeEvent),
0, /* n_preallocs */
(GInstanceInitFunc) thrift_flume_event_instance_init,
NULL, /* value_table */
};
type = g_type_register_static (THRIFT_TYPE_STRUCT,
"ThriftFlumeEventType",
&type_info, 0);
type.timestamp;
}
return type;
}
Parts of the code in main.c:
gpointer eventObj = g_object_new(TYPE_THRIFT_FLUME_EVENT,
"timestamp", 0,
"__isset_timestamp", 0,
"priority", 0,
"__isset_priority", 0,
"body", 0,
"__isset_body", 0,
"nanos", 0,
"__isset_nanos", 0,
"fields", 0,
"__isset_fields", 0,
0);
This is changing in Thrift 0.9.2: Objects generated by the C (GLib) compiler to represent Thrift structs will now expose their members as GObject properties, obviating the risky (and poor) practice of modifying an object's instance structure directly.
Starting with 0.9.2 the preferred way to initialize a struct object will be essentially what the poster originally expected:
ThriftFlumeEvent *event =
g_object_new (TYPE_THRIFT_FLUME_EVENT,
"timestamp", (gint64)t_stamp.tv_sec * 1000,
"priority", priority,
...
NULL);
Note the __isset_ fields are managed by the object itself and should not be set directly.
This was the solution to the problem:
ThriftFlumeEvent *event = g_object_new(TYPE_THRIFT_FLUME_EVENT, 0);
event->timestamp = (gint64)t_stamp.tv_sec * 1000;
event->__isset_timestamp = TRUE;
event->priority = priority;
event->__isset_priority = TRUE;
...
GObject properties are NOT C struct members. You need to install them via g_object_install_property in your class init function https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html . You also need to derive object from GObject (or from any struct that is derived from a GObject).
Note: derived in C means, that it has to have the parent as its first member so it can be cast seamlessly (NOT a pointer to a GObject!)
You should read a book on the topic, it can get quite complex.
Is it possible to notify the module when one of it's sys files was changed? My task is to do a file which controls size of buffer inside the module, I want to resize the buffer when the value in the file is changed.
My other idea (if I can't notify the module) was to check the previous value each time the module is used and then resize the buffer.
Isn't this the purpose of Sysfs?
When you create a kobject and give it a representation in Sysfs (which is a directory), you then create attributes for that object which will become files in that directory. You provide a store and a show callback to the kobject, which are basically equivalents of resp. write and read.
store is what you want here. It looks like this:
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t size);
You receive size bytes within buffer as soon as the virtual file is written in user land.
Have a look at this module which does it (taken from here):
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
struct my_attr {
struct attribute attr;
int value;
};
static struct my_attr my_first = {
.attr.name="first",
.attr.mode = 0644,
.value = 1,
};
static struct my_attr my_second = {
.attr.name="second",
.attr.mode = 0644,
.value = 2,
};
static struct attribute * myattr[] = {
&my_first.attr,
&my_second.attr,
NULL
};
static ssize_t default_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct my_attr *a = container_of(attr, struct my_attr, attr);
return scnprintf(buf, PAGE_SIZE, "%d\n", a->value);
}
static ssize_t default_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t len)
{
struct my_attr *a = container_of(attr, struct my_attr, attr);
sscanf(buf, "%d", &a->value);
return sizeof(int);
}
static struct sysfs_ops myops = {
.show = default_show,
.store = default_store,
};
static struct kobj_type mytype = {
.sysfs_ops = &myops,
.default_attrs = myattr,
};
struct kobject *mykobj;
static int __init sysfsexample_module_init(void)
{
int err = -1;
mykobj = kzalloc(sizeof(*mykobj), GFP_KERNEL);
if (mykobj) {
kobject_init(mykobj, &mytype);
if (kobject_add(mykobj, NULL, "%s", "sysfs_sample")) {
err = -1;
printk("Sysfs creation failed\n");
kobject_put(mykobj);
mykobj = NULL;
}
err = 0;
}
return err;
}
static void __exit sysfsexample_module_exit(void)
{
if (mykobj) {
kobject_put(mykobj);
kfree(mykobj);
}
}
module_init(sysfsexample_module_init);
module_exit(sysfsexample_module_exit);
MODULE_LICENSE("GPL");
Also: you might want to output the buffer size to the user when the entry is read. This is usually the way of doing it. Also make sure the information (read and written) is in a human-readable format to keep up with the Unix philosophy.
Update: see this recent interesting article about Sysfs file creation written by Greg Kroah-Hartman, one of the top kernel developers.