From: jlnance@eos.ncsu.edu (JAMES LEWIS NANCE)
Subject: ANNOUNCE Normal user floppy file systems
Originator: jlnance@volt.ece.ncsu.edu
Keywords: normal floppy
Reply-To: jlnance@eos.ncsu.edu (JAMES LEWIS NANCE)
Organization: North Carolina State University, Project Eos
Date: Fri, 18 Dec 1992 20:09:18 GMT


I read some requests last week for information about allowing a normal user to
mount floppys.  I have written a program which will do this.  I do not think
that it adds any security risk to have it on your system.  If anyone can think
of a way to use it to breach security, send me some mail and I will modify the
program to try to make it more secure.

Read the comments for more doccumentation.

Jim Nance



/*
 * This program provides a safe way for normal users to create, mount, and
 * unmount floppy file systems.  When the floppy is mounted, this program
 * executes the command chmod -f -R a-s to unset all of the suid/sgid bits.
 * a better way would probably be to mount the floppy with an option to ignore
 * set uid bits, but I don't know how to do this.
 *
 * The executable produced by the program must be owned by root, and have
 * the suid bit set.  Ie:
 *     gcc -O -s -o floppy floppy.c
 *     chown root floppy
 *     chmod 4755 floppy
 *
 * If you have a 3.5" drive, you should change the #define FlopBlocks to
 * 2880, or you will have to use the -b2880 flag when you run the program.
 * By default the program mounts the floppy on /tmp/floppy.  You can over ride
 * this with the -m flag or you can change #define MntPoint to be something
 * else.  If you mount the floppy on a nonexistant mount point, the program
 * will create the mount point, and remove it when you unmount the floppy.  If
 * the mount point exists before the program is run, it is not removed by the
 * program when the floppy is unmounted.
 *
 * Summary of commands.  Assume the executable is called floppy.
 *
 * floppy format          # low  level formats the floppy
 * floppy new             # high level formats the floppy
 * floppy mount           # mounts the floppy
 * floppy unmount         # unmounts the floppy
 */

#include "stdlib.h"
#include "string.h"
#include "stdarg.h"
#include "stdio.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/wait.h"
#include "unistd.h"

#define   MntPoint       "/tmp/floppy"
#define   FlopBlocks     "2400"
#define   Ssiz           256

/*VARARGS1*/
void err_exit(char *fmt, ...) {
va_list args;

va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fputs("\n", stderr);
exit(1);
}

/*VARARGS1*/
void new_sys(char *fmt, ...) {
char                     cmd[1024];
va_list args;

va_start(args, fmt);
vsprintf(cmd, fmt, args);
va_end(args);
printf("system: %s\n", cmd);
system(cmd);
}

void print_help(char **argv) {
int                      i;
static char              *cp[] = {
     "\n",
     "options are :\n",
     "    -dX  -> use device X as the floppy drive. Default is /dev/fd0\n",
     "    -eX  -> use program X in place of mkfs    Default is mkfs -c\n",
     "    -bX  -> append X to mkfs command          Default is ",
     FlopBlocks,
     "\n",
     "    -mX  -> mount floppy on directory X       Default is ",
     MntPoint,
     " \n",
     " \n",
     "cmd is one of:\n",
     "    format  -> format the floppy\n",
     "    new     -> create a file system on the floppy\n",
     "    mount   -> mount   the floppy on /tmp/floppy\n",
     "    unmount -> unmount the floppy\n",
     NULL};

printf("USAGE: %s {options} cmd", argv[0]);
for(i=0; cp[i]; fputs(cp[i++],stdout));
}

int main(int argc, char **argv, char **envp) {
char                     dev[Ssiz+1];
char                     mfs[Ssiz+1];
char                     blk[Ssiz+1];
char                     pth[Ssiz+1+20];
char                     *place;
int                      i;
int                      action=0;
uid_t                    uid = getuid();
gid_t                    gid = getgid();
pid_t                    pid;
struct stat              buf;

if(setenv("PATH","/bin:/usr/bin:/usr/local/bin:/etc:/usr/ucb", 1))
     err_exit("Can not set PATH environment variable");

strcpy(dev,"/dev/fd0");
strcpy(pth,MntPoint);
strcpy(blk,FlopBlocks);
strcpy(mfs,"mkfs -c");

for(i=1; i<argc; i++) {
     if(!strncmp(argv[i], "-d", 2)) strncpy(dev,argv[i]+2,Ssiz)[Ssiz]='0'; else
     if(!strncmp(argv[i], "-b", 2)) strncpy(blk,argv[i]+2,Ssiz)[Ssiz]='0'; else
     if(!strncmp(argv[i], "-e", 2)) strncpy(mfs,argv[i]+2,Ssiz)[Ssiz]='0'; else
     if(!strncmp(argv[i], "-m", 2)) strncpy(pth,argv[i]+2,Ssiz)[Ssiz]='0'; else
     if(!strcmp(argv[i],"format" )) action=1;                              else
     if(!strcmp(argv[i],"new"    )) action=2;                              else
     if(!strcmp(argv[i],"mount"  )) action=3;                              else
     if(!strcmp(argv[i],"unmount")) action=4;                              else
     if(!strcmp(argv[i],"help"   )) {print_help(argv); exit(0);}
     }

switch (action) {
     case  1:
          new_sys("fdformat %s", dev);
          break;
     case  2:
          new_sys("%s %s %s",mfs, dev, blk);
          break;
     case  3:
          if(stat(pth, &buf)) if(pid=fork()) wait(pid); else {
               setuid(uid);
               setgid(gid);
               new_sys("mkdir -p %s/floppy.tmp.dir", pth);
               new_sys("chmod 700 %s", pth);
               exit(0);
               }
          if(stat(pth, &buf))        err_exit("Unable to create %s",pth);
          if(buf.st_uid!=uid)        err_exit("You do not own %s", pth);
          if(!(buf.st_mode&S_IFDIR)) err_exit("%s is not a directory",pth);
          new_sys("mount %s %s", dev, pth);
          new_sys("chmod -f -R a-s %s", pth);
          chown(pth, uid, gid);
          break;
     case 4:
          if(stat(pth, &buf))        err_exit("can not stat %s", pth);
          if(buf.st_uid!=uid)        err_exit("You do not own %s", pth);
          if(!(buf.st_mode&S_IFDIR)) err_exit("%s is not a directory",pth);
          new_sys("umount %s", dev);

          for(place=pth; *place; place++);
          strcpy(place,"/floppy.tmp.dir");
          if(!stat(pth, &buf)) {
               *place='\0';
               new_sys("rm -rf %s", pth);
               }
          else *place='\0';

          break;
     default: print_help(argv);
     }

return 0;
}