From samba!concert!gatech!darwin.sura.net!Sirius.dfn.de!chx400!bernina!almesber Mon Sep  7 17:16:12 EDT 1992
Article: 9854 of comp.os.linux
Newsgroups: comp.os.linux
Path: samba!concert!gatech!darwin.sura.net!Sirius.dfn.de!chx400!bernina!almesber
From: almesber@nessie.cs.id.ethz.ch (Werner Almesberger)
Subject: Re: suid for fdformat?
Message-ID: <1992Sep6.130207.11486@bernina.ethz.ch>
Sender: news@bernina.ethz.ch (USENET News System)
Organization: Swiss Federal Institute of Technology (ETH), Zurich, CH
References: <1992Aug30.062444.346@athena.mit.edu>
Date: Sun, 6 Sep 1992 13:02:07 GMT
Lines: 136

In article <1992Aug30.062444.346@athena.mit.edu> hammond@kwhpc.caseng.com (Kevin W. Hammond) writes:
> Should fdformat be installed as a suid program so regular users can format
> floppies, or is it more typically found installed so only root can format
> floppies?

It depends. Formatting is inherently more timing-critical than regular
floppy accesses because some errors can only be detected in the
verification pass. Therefore, it's considered an operation that needs
some awareness on the user's part.

If you can live with users creating bad media on a loaded system,
running fdformat suid isn't a problem. However, you should use the
slightly modified version I've appended to this posting. It assures
that only floppy devices can be formatted (the ioctls may have some
random effect on other devices) and only if the user has write access
to them.

- Werner

---------------------------------- cut here -----------------------------------

/* fdformat.c  -  Low-level formats a floppy disk. */

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <linux/fd.h>


static int ctrl;
struct floppy_struct param;


#define FLOPPY_MAJOR 2
#define SECTOR_SIZE 512
#define PERROR(msg) { perror(msg); exit(1); }


static void format_disk(char *name)
{
    struct format_descr descr;
    int track;
    char dummy;

    printf("Formatting ... ");
    fflush(stdout);
    if (ioctl(ctrl,FDFMTBEG,NULL) < 0) PERROR("\nioctl(FDFMTBEG)");
    for (track = 0; track < param.track; track++) {
	descr.track = track;
	descr.head = 0;
	if (ioctl(ctrl,FDFMTTRK,(int) &descr) < 0) PERROR("\nioctl(FDFMTTRK)");
	printf("%3d\b\b\b",track);
	fflush(stdout);
	if (param.head == 2) {
	    descr.head = 1;
	    if (ioctl(ctrl,FDFMTTRK,(int) &descr) < 0)
		PERROR("\nioctl(FDFMTTRK)");
	}
    }
    if (ioctl(ctrl,FDFMTEND,NULL) < 0) PERROR("\nioctl(FDFMTEND)");
    printf("done\n");
}


static void verify_disk(char *name)
{
    unsigned char *data;
    int fd,cyl_size,cyl,count;

    cyl_size = param.sect*param.head*512;
    if ((data = (unsigned char *) malloc(cyl_size)) == NULL) PERROR("malloc");
    printf("Verifying ... ");
    fflush(stdout);
    if ((fd = open(name,O_RDONLY)) < 0) PERROR(name);
    for (cyl = 0; cyl < param.track; cyl++) {
	printf("%3d\b\b\b",cyl);
	fflush(stdout);
	if (read(fd,data,cyl_size) != cyl_size) PERROR("read");
	for (count = 0; count < cyl_size; count++)
	    if (data[count] != FD_FILL_BYTE) {
		printf("bad data in cyl %d\nContinuing ... ",cyl);
		fflush(stdout);
		break;
	    }
    }
    printf("done\n");
    if (close(fd) < 0) PERROR("close");
}


static void usage(char *name)
{
    char *this;

    if (this = strrchr(name,'/')) name = this+1;
    fprintf(stderr,"usage: %s [ -n ] device\n",name);
    exit(1);
}


main(int argc,char **argv)
{
    int verify;
    char *name;
    struct stat st;

    name = argv[0];
    verify = 1;
    if (argc > 1 && argv[1][0] == '-') {
	if (argv[1][1] != 'n') usage(name);
	verify = 0;
	argc--;
	argv++;
    }
    if (argc != 2) usage(name);
    if (lstat(argv[1],&st) < 0) PERROR(argv[1]);
    if (!S_ISBLK(st.st_mode) || st.st_rdev >> 8 != FLOPPY_MAJOR) {
	fprintf(stderr,"%s: not a floppy device\n",argv[1]);
	exit(1);
    }
    if (access(argv[1],W_OK) < 0) PERROR(argv[1]);
    if ((ctrl = open(argv[1],3)) < 0) PERROR(argv[1]);
    if (ioctl(ctrl,FDGETPRM,(int) &param) < 0) PERROR("ioctl(FDGETPRM)");
    printf("%sle-sided, %d tracks, %d sec/track. Total capacity %d kB.\n",
      param.head ? "Doub" : "Sing",param.track,param.sect,param.size >> 1);
    format_disk(argv[1]);
    if (verify) verify_disk(argv[1]);
}
-- 
   _________________________________________________________________________
  / Werner Almesberger, ETH Zuerich, CH      almesber@nessie.cs.id.ethz.ch /
 / IFW A44  Tel. +41 1 254 7213                 almesberger@rzvax.ethz.ch /
/_BITNET:_ALMESBER@CZHETH5A__HEPNET/CHADNET:_[20579::]57414::ALMESBERGER_/


