View
216
Download
0
Embed Size (px)
Citation preview
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
write()
read()
close()
unlink()
open(“/tmp/foo”, O_RDWR | O_CREAT);
Basic Race Condition Exploit
priv proc
open(“/tmp/foo”, O_RDWR | O_CREAT);
file/tmp/foo
write()
read()
close()
unlink()
hostile proc
open(...)
read()
Basic Race Condition Exploit
priv proc
open(“/tmp/foo”, O_RDWR | O_CREAT);
file/tmp/foo
write()read()
close()
unlink()
hostile proc
chmod()
Basic Race Condition Exploit
priv proc
open(“/tmp/foo”, O_RDWR | O_CREAT);
file/tmp/foo
write()read()
close()
unlink()
hostile proc
chmod()open(...)
Basic Race Condition Exploit
priv proc
open(“/tmp/foo”, O_RDWR | O_CREAT);
file/tmp/foo
write()read()
close()
unlink()
hostile proc
umask()
Basic Race Condition Exploit
priv proc
open(“/tmp/foo”, O_RDWR | O_CREAT);
file/tmp/foo
write()read()
close()
unlink()
hostile proc
umask() open(...)
read()
Basic Race Condition Exploit
priv proc
open(“/tmp/foo”, O_RDWR | O_CREAT);
file/tmp/foo
write()read()
close()
unlink()
hostile proc
umask() symlink(“/tmp/foo”, “/etc/passwd”)
Basic Race Condition Exploit
priv proc
stat(“/tmp/foo”);if (!exists) { open(“/tmp/foo”, O_RDWR | O_CREAT);} else { error(); }
file/tmp/foo
write()read()
close()
unlink()
hostile procumask()
Basic Race Condition Exploit
priv proc
stat(“/tmp/foo”);if (!exists) { open(“/tmp/foo”, O_RDWR | O_CREAT);} else { error(); }
file/tmp/foo
write()read()
close()
unlink()
hostile procumask()
symlink(“/tmp/foo”, “/etc/passwd”)
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!
Building with Ant/Make
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/shcd package1javac *.javacd ..javac *.javaecho <<EOF > ManifestMain-Class: FooClassEOFjar 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/project4INSTROOT=/usr/INSTBIN=${INSTROOT}/binINSTDOC=${INSTROOT}/docDEBUG=-gINCLUDE=${SRCDIR}/includesCFLAGS=${DEBUG} -I ${INCLUDE}LIBDIR=${SRCDIR}/libs
all: myApplicationfoo.o: foo.c
gcc ${CFLAGS} -o foo.o foo.cbar.o: bar.c foo.cgux.o: gux.c foo.cmyApplication: foo.o bar.o gux.o
gcc -o myApplication foo.o bar.o gux.o
Make and the Dependency Graph
myApplication
foo.o
bar.o
gux.o
foo.c
bar.c
gux.c
Must be a DAG Can be arbitrarily hairy
In large projects, thousands of nodes...
Make and the Dependency Graph% makegcc -g -I ./includes -c -o foo.o foo.cgcc -g -I ./includes -c -o bar.o bar.cgcc -g -I ./includes -c -o gux.o gux.cgcc -o myApplication foo.o bar.o gux.o% makemake: Nothing to be done for `all'.% touch gux.c% makegcc -g -I ./includes -c -o gux.o gux.cgcc -o myApplication foo.o bar.o gux.o% makemake: Nothing to be done for `all'.% touch foo.c% makegcc -g -I ./includes -c -o foo.o foo.cgcc -g -I ./includes -c -o bar.o bar.cgcc -g -I ./includes -c -o gux.o gux.cgcc -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 Fileproject: 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)