Operating Systems 2019F: Assignment 4
For this assignment please work on the questions below. There are 12 questions worth 20 points. While you will be able to submit your answers, by default they will not be graded. Instead, a multiple choice quiz (based on the questions below) will be made available by Dec. 2nd and will be due by 4 PM on Dec. 4th. The grade for this quiz will substitute for Assignment 4.
In class on December 4th solutions for the assignment questions below and the Assignment 4 Quiz will be given and discussed.
If you feel your answers to the quiz do not demonstrate what you actually learned, you can make an appointment with Prof. Somayaji to grade your submitted Assignment 4 answers (assuming you submitted them by Dec. 4th) before Dec. 20th.
Questions
- [1] Can you load a Linux kernel module more than once? Explain briefly.
- [1] For the modules we have created in class, does the code run continuously, or does it run in response to certain events? Explain, and be specific.
- [1] When the kernel does a printk(), does it write directly to /var/log/kern.log? Explain.
- [1] The makefile for a Linux kernel module is generally very simple; however, building a module seems to be a bit complicated, generating lots of files. Where is the module build process getting instructions for doing all this work?
- [1] If you change line 22 in the ones module to define CLASS_NAME to be "OSclass", will this change the observable behavior of the module? Explain briefly.
- [1] When doing the work for a system call, how does the kernel keep track of which process made that system call (so it does the work on behalf of that process)?
- [2] How does the format of data returned by getdents(2) differ from that returned by readdir(3) (at a high level)? What is a key motivation for this difference?
- [2] How can you change the magic_prefix for the rootkit without changing the code of the module? How is this information passed to the kernel at runtime?
- [2] When the kernel allocates memory for its own use, does it refer to that memory using virtual or physical addresses? How does the remember module show this?
- [2] What is a significant reason why the kernel uses functions such as copy_to_user() when accessing process memory? Why not just access this memory directly?
- [2] Change the ones module so that it will allow writes, and the first character of whatever is written will become the character that is repeatedly output when reading (instead of '1'). What changes do you need to make?
- [4] How could you make a "spooky rootkit" (based on 3000rootkit) that would randomly (with a .01 probability on each call to getdents) insert a file "BOO!" with an inode of 9999 into the stream of returned files? Note that you can get random bytes using the get_random_bytes() function in the kernel.
Multiple Choice Questions for Quiz
- A kernel module is loaded into
- its own address space, in userspace.
- its own address space, in kernelspace.
- the same address space as the rest of the kernel.
- the same address space as the insmod process that loaded it.
- When does kernel module code normally not run?
- When a module is loaded
- When a module is unloaded
- In response to registered events
- Continuously in the background
- A printk() is just like a printf(), except it goes straight to the kernel log file /var/log/kern.log.
- True
- False
- What does the -C option to make do?
- It says to change to the specified directory before doing anything else
- It defines the output directory for make
- It specifies the compiler make should use to build programs
- It tells make to do a parallel build
- Directories in /sys/class (what doesn't belong)
- contain symbolic links
- list devices defined by different subsystems of the kernel
- are mostly created by kernel modules
- take up disk space
- In the Linux kernel processes are represented as a
- process_struct
- task_struct
- thread_struct
- program_struct
- getdents returns multiple directory entries per call because
- Switching from user space to kernel space is expensive
- Switching from kernel space to user space is expensive
- A directory block on disk will generally hold multiple entries
- All of the above
- How does a kernel module get its parameters?
- The module reads them from a /etc/module.conf config file.
- The module loader writes them to /proc/modules
- The module is passed them through a write system call
- The module has special declarations for parameters that are initialized by the module loading framework
- The module receives them as parameters to its init function
- kmalloc()
- Can be used by regular processes as a faster, lower-level version of malloc
- Allocates memory in the kernel with different priorities
- Only accepts allocation requests that are evenly divisible by the page size
- Returns the physical address of allocated memory
- All of the above
- If the kernel makes use of a userspace pointer as if it was a regular pointer, the kernel could
- return confidential kernel data to a process
- overwrite kernel data it shouldn't
- attempt to write to memory that isn't writable
- attempt to read memory that isn't readable
- all of the above
- When you stat a file, you are getting the contents of
- a directory entry
- an inode
- a file's page table
- a block on disk
- Changing the return value of getdents() (as in 3000rootkit) involves
- changing file permissions
- allocating kernel memory statically
- traversing a set of fixed-length records
- parsing filenames
- all of the above