230 likes | 368 Views
Talking to Threads. Administriva. Grade summary today. Grade Summ: Histogram. Project trends. Main routine: Dijkstra’s. function dijkstraSSP( G , w , s ): // G : complete graph // w : weight function // s : source node (start location) initializeSSPDataStructs(); Set S=new Set();
E N D
Administriva • Grade summary today
Main routine: Dijkstra’s • function dijkstraSSP(G,w,s): • // G: complete graph • // w: weight function • // s: source node (start location) • initializeSSPDataStructs(); • Set S=new Set(); • Queue Q=new PriorityQueue(G.V,d); • while (!Q.isEmpty()) { • Vertex u=Q.extractMin(); • S.add(u); • for (Iterator i=u.neighbors();i.hasNext();) { • Vertex v=i.next(); • relax(u,v,w); • } • }
Group questions: • Give an example of this alg in action on a (small) map from JCiv • How long does this take to run? • What real data structs should you use for S and Q? • Can you take any shortcuts? • What’s wrong w/ negative-weight edges? • Is this guaranteed to get the correct shortest path? Why? (Proof!) • Show that d[v] is the correct shortest path when v is inserted in Set S and that d[v] never changes thereafter. • Hint: think proof by contradiction...
Group questions: • Give an example of this alg in action on a (small) map from JCiv • How long does this take to run? • What real data structs should you use for S and Q? • Can you take any shortcuts? • What’s wrong w/ negative-weight edges? • Is this guaranteed to get the correct shortest path? Why? (Proof!) • Show that d[v] is the correct shortest path when v is inserted in Set S and that d[v] never changes thereafter. • Hint: think proof by contradiction...
wait()ing for Godot... • sleep(n) is good if you know how long you want to delay • What if a thread wants to wait indefinately, or for some other thread to do something? • Check out Object API: • Objecto.wait() -- wait until some other object tells thread to wake up • o.notify() -- wake up one (random) thread that is waiting on o • o.notifyAll() -- wake up every thread that is waiting on o.
More BtS Java • Every Object in Java has a (single) “wait list”. • When a thread adds itself to an Object’s wait list, the thread suspends • Some other thread of execution can then call that Object’s notify() method • One thread wakes up and can now take action • Does not generate an exception; does not change the status of a sleep()ing thread • Must be synchronized on target object to wait() or notify() • Prevents collisions while messing w/ wait list
Use of wait lists DataBucket b; Thread t=new Thread(new Runnable(b) { public Runnable(DataBucket buck) { _bucket=b; } public void run() { while (!bored) { while (_bucket.isEmpty()) { synchronized(_bucket) { _bucket.wait(); } } _bucket.getData(); } }}); // elsewhere... b.addData(data); synchronized(b) { b.notify(); }
Race Cond. & 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 Cond. Exploit priv proc
Basic Race Cond. Exploit priv proc file /tmp/foo open(“/tmp/foo”, O_RDWR | O_CREAT); write() read() close() unlink()
Basic Race Cond. Exploit hostile proc priv proc file /tmp/foo open(“/tmp/foo”, O_RDWR | O_CREAT); open(...) write() read() read() close() unlink()
Basic Race Cond. Exploit hostile proc priv proc file /tmp/foo open(“/tmp/foo”, O_RDWR | O_CREAT); chmod() write() read() close() unlink()
Basic Race Cond. Exploit hostile proc priv proc file /tmp/foo open(“/tmp/foo”, O_RDWR | O_CREAT); open(...) chmod() write() read() close() unlink()
Basic Race Cond. Exploit hostile proc priv proc file /tmp/foo umask() open(“/tmp/foo”, O_RDWR | O_CREAT); write() read() close() unlink()
Basic Race Cond. Exploit hostile proc priv proc file /tmp/foo open(...) umask() open(“/tmp/foo”, O_RDWR | O_CREAT); write() read() read() close() unlink()
Basic Race Cond. Exploit priv proc hostile proc file /tmp/foo umask() symlink(“/tmp/foo”, “/etc/passwd”) open(“/tmp/foo”, O_RDWR | O_CREAT); write() read() close() unlink()
Basic Race Cond. Exploit priv proc hostile proc umask() file /tmp/foo stat(“/tmp/foo”); if (!exists) { open(“/tmp/foo”, O_RDWR | O_CREAT); } else { error(); } write() read() close() unlink()
Basic Race Cond. Exploit priv proc hostile proc umask() file /tmp/foo symlink(“/tmp/foo”, “/etc/passwd”) stat(“/tmp/foo”); if (!exists) { open(“/tmp/foo”, O_RDWR | O_CREAT); } else { error(); } write() read() close() unlink()
Preventing FS Race Conds • 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!