Homework 6 Solutions

22C:116, Spring 1997

Ioana M. Lungeanu
Problem 1 part A:

    There are multiple solutions to this problem.  One is given:

    The root (superuser) creates the .password file in each user's
    home directory.  The root makes the user the owner of the
    .password file, with WR access rights to it.  There is a group
    containing one generic user, call it LOGIN.  The group of the
    .password file is set to LOGIN with R access on it.  The
    user-authentication program (login) runs in the name of this
    LOGIN group.

    file            owner           group           rights

    user_home_dir   user            -               RWX/---/R-X
    .passward       user            LOGIN           RW-/R--/---
    login           LOGIN           -               RWX/---/---

    User_authentication_program may reside, for example in /bin.

    Note that if the user makes his .password file publically
    readable, security may still rest on cryptographic protection
    of the password.  If the user makes his .password file publically
    writable, security is lost.  Users should not do this, and the
    chmod program could be modified to guard against this mistake.
    If the user deletes or renames the .password file, the login
    program would be unable to function, so again, the rm and mv
    commands should guard against this mistake.  Typically, such
    guards would be in the form of a message "Do you really want
    to do this? (Y/N):"

Problem 1 part B:

    The association between a user and the numerical user and
    group IDs is central to system security, so it should not be
    possible for anyone to modify this other than the superuser.
    Placing this in /etc/login, as in current UNIX systems (or in
    something similar, writable only by the system) would make
    perfectly good sense.

        Disclosure of user and group id's causes no problems,
        so this file can be publically readable.  Allowing
        anyone but the system to set them could allow some user
        to masquerade as some other user.

    For the sake of efficient computation, it should be easy for
    the login program to map from login name to home directory,
    so including this in some place like the /etc/login file makes
    sense.  In fact, allowing users to change their login name
    would be possible, so long as users could not select a name
    used by someone else.

        Public disclosure of user login names causes no problems,
        other than allowing users to become the target of junk
        mail.

    The user's preferred shell could be put in the user's personal
    .login file -- it is clearly not needed by other users and
    should be easy for the user to change when needed.

        Public disclosure of a user's preferred shell is never
        needed but causes no problems.  Nobody but the user
        should be able to change their preferred shell.  If the
        user selects a non-functional shell, it is the user's
        fault.  The passwd program (or whatever tool the user
        uses for editing the .login file) should provide some
        degree of protection against setting an invalid preferred
        shell.

    Directory information currently in the .login file (office
    address, phone numbers, etc) can be easily moved to publically
    readable files akin to the .plan and .project files.

        Disclosure of this information should be at the user's
        discression.

Problem 2

    Transmitting Process

        To send a 1, do some CPU-bounded computation for a predefined
        period of time.  One way to measure the time is using the
        system calls alarm() and signal().  The parameter taken by
        alarm specifies an interval in seconds, after which a SIGALARM
        signal is send to the process announcing that the desired time
        has ellapsed.  The same can be done using the time() system
        call.

        To send a 0, wait doing nothing (don't use CPU time) for the
        same time interval.  The system call needed is pause() or
        sleep().  Pause() tells Unix to suspend the process until the
        next signal arrives, and thus is used in conjecture with the
        time measuring system calls from above.  Sleep() takes as
        parameter a time period (and is implemented using pause() and
        alarm()).

    Receiving Process

        There can be a few ways of monitorizing the CPU activity.
        Whichever the way the receiver has to check in each interval
        of the predifened length in time for transmitting a bit.
        The receiver can, for example, do repeatedly a simple
        computation for the bit interval, and count the times it did
        it.  If it did the operations only a "few" number of times,
        the CPU must have been busy, and hence he interprets it as a
        1, otherwise is a 0.  We assume the noise is taken care of
        by other means.  The period of time it does each round is
        measured using the system calls mentioned above.

        There has to be gobal clock when they start this covert
        channel.  For example in the middle of the night when the
        systems are usually not so loaded, at a precise time.  Also
        they need to keep synchronized in their time interval by
        having the same "bit transmittion time" and 'identical'
        overheads. Maybe resinchronize periodically by having preset
        restarting points.

Problem 3

    Here is a reasonable hierarchy for UNIX file classes, with
    notes on what method each subclass adds to the parent's
    method set:

    file -- read()
        directory files -- lookup(name),link(name,file)
        non-directory files -- write()
            random-access files -- seek(), get-sector-size()
		disk-files
                block-device-drivers -- format()
		    floppy-disk
		    scsi-disk
                    CDrom
            sequential-device-drivers
                asynch-line -- set-baud-rate(), hangup()
                parallel-port -- check-paper-empty()
                sockets -- connect()
                pipes

Problem 4

    One commonly suggested solution to break the deadlock is using
    timeouts.  One process waits for a message only a predefined
    limited period of time.  If the message doesn't arrive, the
    process simply ceases waiting for it and goes on to send out
    what ever it has to.

        In fact, timeouts are a deadlock detection method, and
        the timeout method described above only briefly mentions
        its solution to the deadlock resolution -- that of allowing
        unblocking the waiting process as if a message had been
        received; this is quite different from aborting it!

    Another solution would be to have the OS send a special message
    to a waiting process when a deadlock is detected.  From the
    point of view of deadlock resolution methods, this is exactly
    the same method suggested for use with timeouts -- unblock one
    or more of the deadlocked processes and allow it to continue,
    notifying it that the expected message did not arrive.