290 likes | 402 Views
Administrivia. P2 all grades available now Relative importance of scores M1: 30% M2: 30% Rollout: 40% P3 -- good progress so far! Looks like a lot of the “competition” will be on coolness of the GUI... Bad-ass corewarriors a plus too. ;-). Race Conditions & Security.
E N D
Administrivia • P2 all grades available now • Relative importance of scores • M1: 30% • M2: 30% • Rollout: 40% • P3 -- good progress so far! • Looks like a lot of the “competition” will be on coolness of the GUI... • Bad-ass corewarriors a plus too. ;-)
Race Conditions & Security • Atomicity failures can sometimes be exploited to break security on multiprocessing systems • One of the top 10 classes of exploits since... mid-1980’s, at least • 100’s (or more) of reported vulnerabilities • Independent of language: Java will not save you! • Hostile program grabs a shared resource (e.g., file) before it is secured • Beware when writing privileged code! • N.b.: Sometimes your never-intended-to-be- secure code will be run in privileged context!
Basic Race Condition Exploit priv proc
Basic Race Condition Exploit priv proc file /tmp/foo open(“/tmp/foo”, O_RDWR | O_CREAT); write() read() close() unlink()
Basic Race Condition Exploit hostile proc priv proc file /tmp/foo open(“/tmp/foo”, O_RDWR | O_CREAT); open(...) write() read() read() close() unlink()
Basic Race Condition Exploit hostile proc priv proc file /tmp/foo open(“/tmp/foo”, O_RDWR | O_CREAT); chmod() write() read() close() unlink()
Basic Race Condition Exploit hostile proc priv proc file /tmp/foo open(“/tmp/foo”, O_RDWR | O_CREAT); open(...) chmod() write() read() close() unlink()
Basic Race Condition Exploit file /tmp/foo hostile proc priv proc umask() open(“/tmp/foo”, O_RDWR | O_CREAT); write() read() close() unlink()
Basic Race Condition Exploit file /tmp/foo hostile proc priv proc open(...) umask() open(“/tmp/foo”, O_RDWR | O_CREAT); write() read() read() close() unlink()
Basic Race Condition Exploit file /tmp/foo priv proc hostile proc symlink(“/tmp/foo”, “/etc/passwd”) umask() open(“/tmp/foo”, O_RDWR | O_CREAT); write() read() close() unlink()
Basic Race Condition Exploit file /tmp/foo priv proc hostile proc umask() stat(“/tmp/foo”); if (!exists) { open(“/tmp/foo”, O_RDWR | O_CREAT); } else { error(); } write() read() close() unlink()
Basic Race Condition Exploit file /tmp/foo priv proc hostile proc umask() stat(“/tmp/foo”); if (!exists) { open(“/tmp/foo”, O_RDWR | O_CREAT); } else { error(); } symlink(“/tmp/foo”, “/etc/passwd”) write() read() close() unlink()
Preventing Filesystem Race Conditions • Could create “foo” in dir owned/writable only by owner of proc • Can be hard to ensure this • Still have to watch out for filename collisions • Could make file names hard to predict (e.g., picked randomly) • Exploit still possible; hard to make fnames really random • Ultimate answer: use OS atomicity facilities • open(“/tmp/foo”, O_RDWR | O_CREAT | O_EXCL) • Always be on guard!
Automating the Repetitive • Small software: • Type “javac *.java; javadoc *.java” • Maybe “cp *.java ~/distrib_dir; tar czf ~/distrib_dir.tar.gz ~/distrib_dir” • Big software systems • 10k+ Java (and other source lang) files • Many images, data files, support code, etc. • Many directories/subdirs/packages, etc. • Specialized distribution/installation procedures • Doing all of these by hand all the time is a pain in the a**. And error prone. And users won’t do it...
Non-Solution • Shell scripts giving sequences of commands • Doesn’t handle multiple build targets • Doesn’t track dependencies #!/bin/sh cd package1 javac *.java cd .. javac *.java echo <<EOF > Manifest Main-Class: FooClass EOF jar cmf Manifest distro.jar *.class package1/*.class
Multiple Build Targets • For single project may want to: • Build main program • Build support program • Both of above in “debug” or “production” mode • Build docs • Run tests • Export sources/docs for distribution • Auto-create data files • etc... • May want to do any subset (all) of these
Dependencies • Tasks are interdependent -- need to complete one before going on to another • Compile *.java -> *.class before making jar • Build debug version before running tests • Compile code, make jar file, build javadocs, compile user docs, remove scratch files, etc. all before exporting for rollout... • Even source files are interdependent • Compile MondoHashtable.java before StatsTable.java before BSFTrain.java...
Make: the UNIX/C Style Build Tool • In C/C++/FORTRAN/Pascal/Modula-3/etc. have to specify the source dependencies by hand • “Do foo.c before bar.c; when you have foo.o and bar.o, make the executable gux” • Know that if “foo.o” is newer than “foo.c”, you don’t have to rebuild it (redundant) • Need support for many different compilers/languages • Need support for arbitrary tools (create directories, move files, tar, cvs, etc.) • Also multiple targets, conditional compilation, etc.
Example Makefile SRCDIR=${HOME}/sources/project4 INSTROOT=/usr/ INSTBIN=${INSTROOT}/bin INSTDOC=${INSTROOT}/doc DEBUG=-g INCLUDE=${SRCDIR}/includes CFLAGS=${DEBUG} -I ${INCLUDE} LIBDIR=${SRCDIR}/libs all: myApplication foo.o: foo.c gcc ${CFLAGS} -o foo.o foo.c bar.o: bar.c foo.c gux.o: gux.c foo.c myApplication: foo.o bar.o gux.o gcc -o myApplication foo.o bar.o gux.o
Make and the Dependency Graph • Must be a DAG • Can be arbitrarily hairy • In large projects, thousands of nodes... foo.o foo.c bar.o bar.c myApplication gux.o gux.c
Make and the Dependency Graph % make gcc -g -I ./includes -c -o foo.o foo.c gcc -g -I ./includes -c -o bar.o bar.c gcc -g -I ./includes -c -o gux.o gux.c gcc -o myApplication foo.o bar.o gux.o % make make: Nothing to be done for `all'. % touch gux.c % make gcc -g -I ./includes -c -o gux.o gux.c gcc -o myApplication foo.o bar.o gux.o % make make: Nothing to be done for `all'. % touch foo.c % make gcc -g -I ./includes -c -o foo.o foo.c gcc -g -I ./includes -c -o bar.o bar.c gcc -g -I ./includes -c -o gux.o gux.c gcc -o myApplication foo.o bar.o gux.o
Coolness of Make • Auto-tracks dependencies • ~Simple support for conditional compilation • Variables for repeatedly used constructs (CFLAGS, LIBDIR, CLASSPATH, etc.) • Can write arbitrary commands for any rule • Extensibility==write command lines/shell script • Supports rule patterns (.o: .c) • Universal -- available on any *nix, DOS/Win, etc.
Bogusness of Make • Antiquated syntax • hard to read/maintain • Tracks, but doesn’t auto-detect source file dependencies • Dependency model radically different than Java dependencies • javac wants to figure them out itself • Multiple re-compilation of the same file • Every invocation of javac==new JVM (slow)
Ant: Java’s Answer to Make • New entry into the build tool arena • Freeware project available from apache.org • Runs in Java itself • Only creates one JVM, regardless of # of compilations • Has direct access to javac’s dependency engine • Extensible via new Java modules/subclassing
Parts of an Ant Buildfile • One Project • Just a name for the whole file, place to put comments, specify top-level dirs & vars, etc. • One or more Targets for that project • Target==named build goal • Executable • Documentation • Tests • Export • One or more Tasks for each Target • Task specifies how to achieve that target
A “Conceptual” Ant File project: CS351 { BASEDIR=${HOME}/projects/p3 MOD1=${BASEDIR}/src/module1 MOD2=${BASEDIR}/src/module2 DOCDIR=${BASEDIR}/documentation Target: buildExecutable { Task: compileAllFiles { cd ${MOD1} javac *.java cd ${MOD2} javac *.java } Task: makeJarFile { ... } } Target: buildDocs { Task: mkDocDir { if (!exists(${DOCDIR}) { mkdir ${DOCDIR} } } Task: buildJavaDocs { ... }
Coolness of Ant • Already knows about most standard Java things that you want to do • Understands Java’s dependency model, etc. • Built-in recursive behavior for Java packages • Don’t have to enumerate all sourcefiles • Extensible • Fast (mostly) • (many) IDEs understand it natively
Bogusness of Ant • Modern, cutting edge syntax (XML) • Hard to read/maintain • Built-in recursive behavior for Java packages • Hard to track, easy to get wrong, hard to override • Tightly fitted to Java • Extension==write new Java class to do new task (ick)