Scripts are wonderful

The past couple of weeks have been quite eventful with some interesting scripts being written and tested out. So, lets talk about them.

There are some cases where the values returned by memory allocation functions like kmalloc, kzalloc, kcalloc, kmem_cache_alloc, kmem_cache_zalloc, kmem_cache_alloc_node, kmalloc_node and kzalloc_node are type casted, which is unnecessary. On sending a coccinelle semantic patch making the change, I realised from the feedback that not only these functions, but most void * values need not be type casted.
Here is a part of the initial script:

@@
type T;
@@

– (T *)
(\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(…))

I started working on making the script more generic. But there were many cases where the void * has to be casted to make it useful. These are listed with examples to make them clear, but this may not be comprehensive:

1. Arithmetic operations. eg: sch->padded = (char *) sch – (char *) p; [Code]

2. Structure dereference. eg: n = ((struct rt6_info *)v)->dst.rt6_next; [Code]

3. Indirection operation. eg: *((u8 *) ptr++) = type; [Code]

4. Array dereference. eg: key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; [Code]

5. Cases where the type cast is __user, __ioremap, __force etc. which are not data types but macros. eg:  memcpy(to, (__force void*)from, n); [Code]

6. Casting of NULL before dereferencing. eg: dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data));[Code]

7. Use of sizeof on the casted value. eg: target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;[Code]

Taking into consideration these cases, I decided to handle only a assignment case initially. Here, is the patch.

@r@
void* e;
identifier a;
type T;
position p;
@@

a = (T@p *)e

@script:python@
t << r.T;
pc << r.p;
@@
if “__” in t: //To deal with cases like __user
cocci.include_match(False)

@remove_cast@
expression e;
identifier a;
type T;
position r.p;
@@

a =
-(T@p *)
e

Now, I am working on extending the patch to generic cases like when arguments are passes to a function with typecasting etc. being careful not to generate false positives.

And yeah for those following the blog, some more devm_ patches have got into the kernel and more will be following. I’ll be updating the list below soon. Many more interesting scripts and the complete version will be updated soon.. so keep learning and have fun ūüôā

Advertisements

Coccinelle format and IRQs

Hey! The last couple of weeks have been great. I have understood and played with the format of the Coccinelle semantic patches in the kernel so lets talk about it a bit. A Coccinelle script has 4 modes of running – context, report, org and patch. The context mode just marks out the changes that will be done without actually making the changes, so a developer can checkout if some changes are unnecessary or erroneous and ignore those files/ change the Coccinelle script. Then there’s a report mode which is the most frequently used mode and it just logs a custom message which has the lines and files with the warning or error. The org mode is rarely used and also lists down the cases in a TODO format with exact line number and column positions with the modification to be done. The patch mode is the default mode and it applies the changes to the files where it detects the problem.¬† Soon, there will be some semantic patches developed by me in the kernel for linux developers to check out for any warnings being introduced and also to fix existing issues!

There is another major thing that came to my notice while working with shifting resource allocation to managed interfaces. The call to request_irq allocates interrupt resources and enables the interrupt line and IRQ handling. From the point this call is made your handler function may be invoked. Since the handler function must clear any interrupt the board raises, it takes care both to initialize the hardware and to set up the interrupt handler in the right order. While using managed interfaces for allocating resources we skip the corresponding functions to free the resources like kfree, free_irq etc. as the resource is freed by the devres interface on driver detachment. But there may be a race condition in the frees. There may be instances where the hardware resources are freed before interrupt resources get freed. In such cases, the interrupt handler will try accessing resources that no longer exist leading to an error. So, we need to be careful when shifting resources allocated by request_irq/request_threaded_irq to the managed devm_request_irq function.

 Here are some details of the function:
int request_irq (unsigned int irq, irq_handler_t  handler, unsigned long  irqflags, const char * devname, void * dev_id);

irq      : Interrupt line to allocate
handler  : Function to be called when the IRQ occurs
irqflags : Interrupt type flags
devname  : An ascii name for the claiming device
dev_id     : A cookie passed back to the handler function