setxattr

#kmalloc-variable#xattr#setxattr#heapspray
Slabkmalloc-variable (size-controlled)
Requiresopen-write-syscall-access
Alt Requiresuaf-or-double-free-primitive (for object-overlap exploitation)
Givescontrolled-size-heap-groomoverlap-with-arbitrary-kmalloc-N-object

The setxattr() syscall allows userspace to attach arbitrary meta data to a filesystem inode object. It is useful because the kernel must allocate memory to store the xattr value, and the contents of that allocation can be controlled from userspace.


GLibc Function

int setxattr(
    const char *path,
    const char *name,
    const void *value,
    size_t size,
    int flags
);

The important arguments for heap spraying are:

  • path → filesystem object to attach the xattr to
  • name → xattr name
  • value → attacker-controlled data
  • size → size of the data copied into the kernel
  • flagsXATTR_CREATE / XATTR_REPLACE / 0

For example:

char buf[0x100];
memset(buf, 'A', sizeof(buf));
setxattr("/home/user","user.x",buf,0x100,XATTR_CREATE);

2. Why Spray setxattr()

  • The primary reason is that kmem cache object is created for the attacker controlled size and moreover, the content put into that object is attacker controlled.
  • However, remember that the object allocated is just for a temporary storage (isetxattr_copy()) until a persistent data structure is created (simple_xattr_alloc()) and mapped to the corresponding inode. Eventually, this object is freed back the kmem. Therefore, this technique can be used to overwrite overlapping data structures in memory.
  • For more implementation details, check out fs/xattr.c

3. Exploitation Context

setxattr() is particularly useful for:

  • Heap Grooming — repeatedly create xattrs to populate a particular kmalloc cache.
  • Controlled Data — the xattr value is copied from userspace, allowing control over the allocation’s contents.

The important distinction is:

setxattr() is useful not simply because it allocates memory, but because it gives you a kernel allocation whose contents are substantially controlled by userspace.


4. How to?

Minimal helper:

#include <sys/xattr.h>

static int spray_xattr(const void *buf, size_t size,int count)
{
	int ret;
	for(int i=0;i<count;i++){
		ret = setxattr("/home/user","user.x",buf,size,XATTR_CREATE);
		if(ret<0)
			perror("setxattr")'
	}
    return 0; 
}

uint8_t buf[0x100];
// set the buf with correct data to overwrite already existing object
set_buf(buf);
spray_xattr(buf, sizeof(buf),0x50)

To inspect the resulting xattrs:

getfattr -d /home/user