$ checksec babydriver.ko [*] '/usr/class/kernel_pwn/CISCN2017-babydriver/babydriver/babydriver.ko' Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x0)
/** * alloc_chrdev_region() - register a range of char device numbers * @dev: output parameter for first assigned number * @baseminor: first of the requested range of minor numbers * @count: the number of minor numbers required * @name: the name of the associated device or driver * * Allocates a range of char device numbers. The major number will be * chosen dynamically, and returned (along with the first minor number) * in @dev. Returns zero or a negative error code. */ intalloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, constchar *name)
/** * cdev_init() - initialize a cdev structure * @cdev: the structure to initialize * @fops: the file_operations for this device * * Initializes @cdev, remembering @fops, making it ready to add to the * system with cdev_add(). */ voidcdev_init(struct cdev *cdev, conststruct file_operations *fops)
/** * cdev_add() - add a char device to the system * @p: the cdev structure for the device * @dev: the first device number for which this device is responsible * @count: the number of consecutive minor numbers corresponding to this * device * * cdev_add() adds the device represented by @p to the system, making it * live immediately. A negative error code is returned on failure. */ intcdev_add(struct cdev *p, dev_t dev, unsigned count)
/* This is a #define to keep the compiler from merging different * instances of the __key variable */ #define class_create(owner, name) \ ({ \ static struct lock_class_key __key; \ __class_create(owner, name, &__key); \ })
/** * class_create - create a struct class structure * @owner: pointer to the module that is to "own" this struct class * @name: pointer to a string for the name of this class. * @key: the lock_class_key for this class; used by mutex lock debugging * * This is used to create a struct class pointer that can then be used * in calls to device_create(). * * Returns &struct class pointer on success, or ERR_PTR() on error. * * Note, the pointer created here is to be destroyed when finished by * making a call to class_destroy(). */ structclass *__class_create(structmodule *owner, constchar *name, structlock_class_key *key) /** * device_create - createsadeviceandregistersitwithsysfs * @class: pointer to the structclassthatthisdeviceshouldberegisteredto * @parent: pointer to the parent structdeviceofthisnewdevice, ifany * @devt: the dev_tfor the char device to be added * @drvdata: the data to be added to the device for callbacks * @fmt: stringfor the device's name * * This function can be used by char device classes. A structdevice * willbecreatedinsysfs, registeredtothespecifiedclass. * * A "dev" filewillbecreated, showingthedev_tforthedevice, if * thedev_tisnot 0,0. * Ifapointertoaparentstructdeviceispassedin, thenewlycreated * structdevicewillbeachildofthatdeviceinsysfs. * Thepointertothestructdevicewillbereturnedfromthecall. * Anyfurthersysfsfilesthatmightberequiredcanbecreatedusingthis * pointer. * * Returns &structdevicepointeronsuccess, orERR_PTR() onerror. * * Note: the struct class passed to this function must have previously * been created with a call to class_create(). */ struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, constchar *fmt, ...)
初始时,init 函数通过调用 class_create 函数创建一个 class 类型的类,创建好后的类存放于sysfs下面,可以在 /sys/class中找到。
/** * kmalloc - allocate memory * @size: how many bytes of memory are required. * @flags: the type of memory to allocate. * * kmalloc is the normal method of allocating memory * for objects smaller than page size in the kernel. * * The allocated object address is aligned to at least ARCH_KMALLOC_MINALIGN * bytes. For @size of power of two bytes, the alignment is also guaranteed * to be at least to the size. * * The @flags argument may be one of the GFP flags defined at * include/linux/gfp.h and described at * :ref:`Documentation/core-api/mm-api.rst <mm-api-gfp-flags>` * * The recommended usage of the @flags is described at * :ref:`Documentation/core-api/memory-allocation.rst <memory_allocation>` * * Below is a brief outline of the most useful GFP flags * * %GFP_KERNEL * Allocate normal kernel ram. May sleep. * * %GFP_NOWAIT * Allocation will not sleep. * * %GFP_ATOMIC * Allocation will not sleep. May use emergency pools. * * %GFP_HIGHUSER * Allocate memory from high memory on behalf of user. * * Also it is possible to set different flags by OR'ing * in one or more of the following additional @flags: * * %__GFP_HIGH * This allocation has high priority and may use emergency pools. * * %__GFP_NOFAIL * Indicate that this allocation is in no way allowed to fail * (think twice before using). * * %__GFP_NORETRY * If memory is not immediately available, * then give up at once. * * %__GFP_NOWARN * If allocation fails, don't issue any warnings. * * %__GFP_RETRY_MAYFAIL * Try really hard to succeed the allocation but fail * eventually. */ static __always_inline void *kmalloc(size_t size, gfp_t flags) { if (__builtin_constant_p(size)) { #ifndef CONFIG_SLOB unsignedint index; #endif if (size > KMALLOC_MAX_CACHE_SIZE) return kmalloc_large(size, flags); #ifndef CONFIG_SLOB index = kmalloc_index(size);
/* * The security context of a task * * The parts of the context break down into two categories: * * (1) The objective context of a task. These parts are used when some other * task is attempting to affect this one. * * (2) The subjective context. These details are used when the task is acting * upon another object, be that a file, a task, a key or whatever. * * Note that some members of this structure belong to both categories - the * LSM security pointer for instance. * * A task has two security pointers. task->real_cred points to the objective * context that defines that task's actual details. The objective part of this * context is used whenever that task is acted upon. * * task->cred points to the subjective context that defines the details of how * that task is going to act upon another object. This may be overridden * temporarily to point to another security context, but normally points to the * same context as task->real_cred. */ structcred { atomic_t usage; #ifdef CONFIG_DEBUG_CREDENTIALS atomic_t subscribers; /* number of processes subscribed */ void *put_addr; unsigned magic; #define CRED_MAGIC 0x43736564 #define CRED_MAGIC_DEAD 0x44656144 #endif kuid_t uid; /* real UID of the task */ kgid_t gid; /* real GID of the task */ kuid_t suid; /* saved UID of the task */ kgid_t sgid; /* saved GID of the task */ kuid_t euid; /* effective UID of the task */ kgid_t egid; /* effective GID of the task */ kuid_t fsuid; /* UID for VFS ops */ kgid_t fsgid; /* GID for VFS ops */ unsigned securebits; /* SUID-less security management */ kernel_cap_t cap_inheritable; /* caps our children can inherit */ kernel_cap_t cap_permitted; /* caps we're permitted */ kernel_cap_t cap_effective; /* caps we can actually use */ kernel_cap_t cap_bset; /* capability bounding set */ kernel_cap_t cap_ambient; /* Ambient capability set */ #ifdef CONFIG_KEYS unsignedchar jit_keyring; /* default keyring to attach requested * keys to */ structkey __rcu *session_keyring;/* keyring inherited over fork */ structkey *process_keyring;/* keyring private to this process */ structkey *thread_keyring;/* keyring private to this thread */ structkey *request_key_auth;/* assumed request_key authority */ #endif #ifdef CONFIG_SECURITY void *security; /* subjective LSM security */ #endif structuser_struct *user;/* real user ID subscription */ structuser_namespace *user_ns;/* user_ns the caps and keyrings are relative to. */ structgroup_info *group_info;/* supplementary groups for euid/fsgid */ structrcu_headrcu;/* RCU deletion hook */ };
/* Create pseudo tty master slave pair and set terminal attributes according to TERMP and WINP. Return handles for both ends in AMASTER and ASLAVE, and return the name of the slave end in NAME. */ int openpty(int *amaster, int *aslave, char *name, conststruct termios *termp, conststruct winsize *winp) { #ifdef PATH_MAX char _buf[PATH_MAX]; #else char _buf[512]; #endif char *buf = _buf; int master, ret = -1, slave = -1;
*buf = '\0';
master = getpt (); if (master == -1) return-1;
if (grantpt (master)) goto on_error;
if (unlockpt (master)) goto on_error;
#ifdef TIOCGPTPEER /* Try to allocate slave fd solely based on master fd first. */ slave = ioctl (master, TIOCGPTPEER, O_RDWR | O_NOCTTY); #endif if (slave == -1) { /* Fallback to path-based slave fd allocation in case kernel doesn't * support TIOCGPTPEER. */ if (pts_name (master, &buf, sizeof (_buf))) goto on_error;
slave = open (buf, O_RDWR | O_NOCTTY); if (slave == -1) goto on_error; }
/* XXX Should we ignore errors here? */ if (termp) tcsetattr (slave, TCSAFLUSH, termp); #ifdef TIOCSWINSZ if (winp) ioctl (slave, TIOCSWINSZ, winp); #endif
*amaster = master; *aslave = slave; if (name != NULL) { if (*buf == '\0') if (pts_name (master, &buf, sizeof (_buf))) goto on_error;
structmutexatomic_write_lock; structmutexlegacy_mutex; structmutexthrottle_mutex; structrw_semaphoretermios_rwsem; structmutexwinsize_mutex; spinlock_t ctrl_lock; spinlock_t flow_lock; /* Termios values are protected by the termios rwsem */ structktermiostermios, termios_locked; structtermiox *termiox;/* May be NULL for unsupported */ char name[64]; structpid *pgrp;/* Protected by ctrl lock */ structpid *session; unsignedlong flags; int count; structwinsizewinsize;/* winsize_mutex */ unsignedlong stopped:1, /* flow_lock */ flow_stopped:1, unused:BITS_PER_LONG - 2; int hw_stopped; unsignedlong ctrl_status:8, /* ctrl_lock */ packet:1, unused_ctrl:BITS_PER_LONG - 9; unsignedint receive_room; /* Bytes free for queue */ int flow_change;
structtty_struct *link; structfasync_struct *fasync; int alt_speed; /* For magic substitution of 38400 bps */ wait_queue_head_t write_wait; wait_queue_head_t read_wait; structwork_structhangup_work; void *disc_data; void *driver_data; structlist_headtty_files;
#define N_TTY_BUF_SIZE 4096
int closing; unsignedchar *write_buf; int write_cnt; /* If the tty has a pending do_SAK, queue it here - akpm */ structwork_structSAK_work; structtty_port *port; };
/* * At this label, code paths which return to kernel and to user, * which come from interrupts/exception and from syscalls, merge. */ GLOBAL(restore_regs_and_iret) RESTORE_EXTRA_REGS restore_c_regs_and_iret: RESTORE_C_REGS REMOVE_PT_GPREGS_FROM_STACK 8 INTERRUPT_RETURN