All pastes #953653 Raw Edit

Something

public text v1 · immutable
#953653 ·published 2008-03-23 06:33 UTC
rendered paste body
							March 8, 2008

				Project #0
				==========

This project is due Saturday March 29th at 11:59pm.  You should send me
email at "kensmith@dcsl.buffalo.edu" saying you are done.

This project description is very complicated.  You will need to read it
once, then wait a while to let things "settle in", then read it again,
and repeat that cycle a couple of times.  Even then you will probably
have questions.  Feel free to ask.

General Overview
----------------

You are to implement an in-kernel "mailbox facility".  Processes will
be allowed to write a message to a mailbox, and then read the message
from the mailbox.  It will be possible for different processes to
do the writing/reading, and even different processes run by different
users as described below.  There are to be two general types of mailboxes,
"Global" and "User".  For both types you will need to keep track of
who owns the mailbox, what group(s) that user had been in when they
created the mailbox, and permissions similar to the UNIX file permissions
that determine what operations if any other users are allowed to do
on the mailbox.  Once created the mailbox should accept only one
message at a time - the message will need to be read (and thus removed
from the mailbox) before another message can be written to it, or
the mailbox will need to be cleared without reading the message (a
separate system call will be allowed for that).

Specifics
---------

All of the new system calls you write for the mailboxes will have a
"mailbox type" argument that says whether it is a User Mailbox or
a Global Mailbox.  In the descriptions given below I will give the
new system call names and exactly what the arguments to each system
call should be.  You must use these descriptions.  That way my test
programs can be used to test your kernel in case I don't particularly
like what you come up with for test programs.   :-) 

Before mailboxes can be created a 'mailbox group' needs to be created.
Individual non-root users may only create their own "User Mailbox
Group" which you can keep track of using their user-id.  Once they
have created their "User Mailbox Group" they may then create named
mailboxes inside of it.  For root-owned processes they are allowed
to create "User Mailbox Groups" that are owned by other user-ids.
And only root-owned processes may create "Global Mailbox Groups".

Global Mailbox Groups are to be kept track of by their name.  Names
can be up to 8 characters.

The system calls you should add (in this order, with the system call
numbers starting off with 484) are:

  create_mboxgr(int type, char *name, uid_t uid, int perms)
	The type passed in should be 0 to indicate this is a "User
	Mailbox Group", a value of 1 should indicate a "Global Mailbox
	Group".  For "User Mailbox Groups" the name argument is meaningless
	and should be a NULL pointer, anything else is an error.  If the
	uid specified is zero that means "Create a mailbox group for the
	user who called the system call".  So if user 'kensmith' runs a
	program that calls create_mboxgr(2) with the uid argument zero
	that means create the mailbox group for user kensmith.  Normal
	users are not allowed to create mailbox groups for other users,
	but root-owned processes are allowed to do that.  In the case of
	a root-owned process calling create_mboxgr(2) it may provide a
	non-zero value for uid and the resulting mailbox group should be
	owned by that uid.  The "perms" argument should be a bitmask
	exactly like the file permission - bits 2, 1, and 0 should be
	"read", "write", and "admin" permissions for "other".  Bits
	5, 4, and 3 should be "read", "write", and "admin" permissions
	for processes that are in one of the same groups as the process
	that created the mailbox group (you should record all group(s)
	that process had been in as part of your mailbox group data
	structure).  And bits 8, 7, and 6 should be "read", "write",
	and "admin" for the owner of the mailbox group.  There should
	be a limit of 50 Global Mailbox Groups.

  destroy_mboxgr(int type, char *name, uid_t uid)
	Type, name, and uid are all as described above for create_mboxgr(2).
	So, for example, the name should be NULL if type is 0.  If the
	process that calls destroy_mboxgr(2) has "admin" permissions on the
	mailbox group it should be allowed to destroy the mailbox group.
	Any mailboxes that exist for that group should also be destroyed
	as part of this operation - it is NOT an error to call this with
	mailboxes still in existence.

  join_mboxgr(char *name, pid_t pid)
	This is a request for a process to join a Global Mailbox Group.
	If the pid argument is 0 then the process that called join_mboxgr(2)
	should join that Global Mailbox Group, but if pid is non-zero
	the process with that process-id should be made part of the
	Global Mailbox Group instead.  The Global Mailbox Group must already
	have been created, and whether the identified process should be
	allowed into the Global Mailbox Group should be determined by
	whether it has either "read" or "write" permissions (or both)
	based on who owns the Mailbox Group, what groups it's in, etc.
	A root-owned process that calls join_mboxgr(2) may put any process
	into any (existing) Global Mailbox Group.  Once a process is placed
	into a Global Mailbox Group any child processes it creates from
	that point on should inherit the Global Mailbox Group from the
	parent process.  Note this dictates to some degree where you
	will need to record this information.  A NULL pointer for the
	name argument indicates that the calling processes wants to not
	be in any Global Mailbox Group.

  create_mbox(int type, char *name, uid_t uid, int perms)
	All arguments are as described above for the other system calls.
	Whether this operation should be allowed depends on whether the
	calling process has "admin" privileges on the "Mailbox Group"
	the mailbox is being created in.  If type is 1 that indicates
	this is a Global Mailbox, and the name of the Global Mailbox
	Group should have been set by a call to join_mboxgr(2) beforehand
	(or it could have been inherited from a parent process - either
	way the Global Mailbox Group for the process must be set).
	The name argument will be the mailbox name.  If uid is 0 then the
	mailbox should be created in the User Mailbox Group for the
	user the calling process is owned by.  Note that non-root
	processes may provide a non-zero value here.  If that other
	user had created a User Mailbox Group with permissions such
	that other user(s) are granted "admin" permissions then those
	other users are allowed to create mailboxes in that Mailbox
	Group.  You should record the ownership and group information
	based on the calling process, even if the resulting mailbox
	is going into a different user's User Mailbox Group.  The name
	of the mailbox may be up to 255 characters.  A maximum of eight
	mailboxes should be allowed for any Mailbox Group (either User
	or Global).

  destroy_mbox(int type, char *name, uid_t uid)
	The arguments are as described above.  This should be allowed
	if the calling process has "admin" permissions on the mailbox.

  write_mbox(int type, char *name, uid_t uid, char *message, int flag)
	This writes to the identified mailbox, based on type, mailbox name,
	and if type had been 1 the Global Mailbox Group of the process
	that called write_mbox(2).  Use the same semantics as above for
	the uid argument.  This should succeed if the calling process
	had "write" permissions to the identifed Mailbox.  This should
	return an appropriate error code for situations like permission
	being denied, etc.  Note that it's possible for things like
	the User Mailbox Group or Global Mailbox Group to have been
	destroyed by some other process while this process was running
	so be careful with error checking here.  The message can be up
	to 255 characters.  If the mailbox being written to already
	had a message in it that message should not be overwritten.
	For this case if the 'flag' argument is 0 the calling process
	should be put to sleep until writing to the mailbox becomes
	possible (it is either read or cleared).  If the 'flag' argument
	is anything other than 0 the error code EWOULDBLOCK should be
	returned instead.

  read_mbox(int type, char *name, uid_t uid, char *message, int len, int flag)
	This reads from the identified mailbox, using the same semantics
	as write_mbox(2).  The calling process must have "read" permissions
	on the identified mailbox.  "message" is where the message should
	be copied to.  "len" is how many bytes the calling process made
	the buffer and only that many bytes should be copied out if the
	message in the mailbox is larger.  The "flag" argument gives the
	same information as it did for write_mbox(2), so if it is 0 and
	there is no message in the mailbox the calling process should be
	put to sleep.  Once a message is read from a mailbox it should
	be considered "gone", another message would need to be written
	to the mailbox before another read from it should be allowed,
	even if the calling process only got part of the message because
	"len" wasn't big enough.  This is the only system call you are to
	add that should return anything other than an error code.  This
	one should return the number of bytes worth of message that got
	copied out to the user (the smaller of len or how big the
	message itself had been).  Look at how write(2) handles returning
	how many bytes get transferred and how it handles returning error
	codes since you may still need to return "permission denied"
	error codes.  And again it's possible other processes destroyed
	Mailbox Groups or mailboxes themselves so be careful with error
	checking.

  clear_mbox(int type, char *name, uid_t uid)
	Remove a message from the identified mailbox without actually
	reading it.  This requires "read" or "admin" permissions for
	the calling process on the identified mailbox.

Notes
-----

Note that in some cases I mentioned things that root-owned processes are
allowed to do versus non-root-owned processes.  I did not spell out
everything I expect however.  You should now have a feel for what things
root is allowed to do, what non-root is allowed to do, etc.  Part of
your grade will be based on you doing the proper checks.  You will be
adding data structures to the kernel to help you keep track of the
mailbox groups and mailboxes themselves.  Many of them will need to
be dynamically allocated using the kernel's malloc(9) function.  Keep
in mind FreeBSD is SMP - another part of your grade will be based
on how well you protect your new data structures from being accessed
by multiple threads at the same time.  You will also need to have written
some test programs to help you test your new system calls.  Note that I
tend to prefer small test programs that take command line arguments
for "interesting" things (e.g. uid, name, etc) and do small tasks instead
of one big test program that does a pre-defined (and not easily changable)
sequence of events.

What to Hand In
---------------

As mentioned all I expect is email saying "I'm done".  However in addition
to the kernel code itself you will need to provide, in ~/OSI/Project_0 the
following:

	1) Manual pages for each of the new system calls.  See the
	   Lab Manual for hints on how to make these.
	2) Your test programs, both source code and executables.
	3) CHANGES - a file that lists what file(s) you needed to
	   change as part of doing this project and a brief description
	   of what you changed.
	4) TESTING - a file that contains a description of how you tested
	   your work.  Describe briefly what each of the test programs
	   do, and then describe how you used them to test various aspects
	   of the new system calls.

If during testing you set your kernel up to print out debugging information
make sure you turn that off before handing in your work.  Extra stuff
written during grading will cost a few points.


-- Ken Smith - From there to here, from here to | kensmith@cse.buffalo.edu there, funny things are everywhere. | - Theodore Geisel |