diff --git a/history.txt b/history.txt index 74dc5e5dcb9aaba78b22f340ca5f56344aebc058..8d49bd5ff20e7dc29cd711d677c22853a6e61a8e 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,15 @@ +2011-06-04 zzz + * NBigI: Recognize Android + * KeyGenerator: Restore old return type to not break ABI (thx kytv) + * Router: + - Add a lock for reading/writing the router.info file + - Check our RouterInfo validity after reading and before saving, + to catch fatal errors sooner + +2011-06-03 zzz + * Android: More build updates, start working on JNI for GMP + * Build: Fix dependency issue cause by misspelled file name + 2011-06-02 zzz * Android: Build fixes * Crypto: diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index 1245a6208605d2b497d70e4fec0f511d24c78cb2..6fb67b53b91532ed0413ef9ac7f82fe95619a76b 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -63,6 +63,7 @@ public class Router { /** full path */ private String _configFilename; private RouterInfo _routerInfo; + public final Object routerInfoFileLock = new Object(); private long _started; private boolean _higherVersionSeen; //private SessionKeyPersistenceHelper _sessionKeyPersistenceHelper; @@ -312,6 +313,9 @@ public class Router { public RouterInfo getRouterInfo() { return _routerInfo; } + /** + * Caller must ensure info is valid - no validation done here + */ public void setRouterInfo(RouterInfo info) { _routerInfo = info; if (_log.shouldLog(Log.INFO)) @@ -452,6 +456,8 @@ public class Router { } ri.sign(key); setRouterInfo(ri); + if (!ri.isValid()) + throw new DataFormatException("Our RouterInfo has a bad signature"); Republish r = new Republish(); if (blockingRebuild) r.timeReached(); @@ -1582,13 +1588,14 @@ private static class ShutdownHook extends Thread { /** update the router.info file whenever its, er, updated */ private static class PersistRouterInfoJob extends JobImpl { - private Log _log; public PersistRouterInfoJob(RouterContext ctx) { super(ctx); } + public String getName() { return "Persist Updated Router Information"; } + public void runJob() { - _log = getContext().logManager().getLog(PersistRouterInfoJob.class); + Log _log = getContext().logManager().getLog(PersistRouterInfoJob.class); if (_log.shouldLog(Log.DEBUG)) _log.debug("Persisting updated router info"); @@ -1598,15 +1605,17 @@ private static class PersistRouterInfoJob extends JobImpl { RouterInfo info = getContext().router().getRouterInfo(); FileOutputStream fos = null; - try { - fos = new SecureFileOutputStream(infoFile); - info.writeBytes(fos); - } catch (DataFormatException dfe) { - _log.error("Error rebuilding the router information", dfe); - } catch (IOException ioe) { - _log.error("Error writing out the rebuilt router information", ioe); - } finally { - if (fos != null) try { fos.close(); } catch (IOException ioe) {} + synchronized (getContext().router().routerInfoFileLock) { + try { + fos = new SecureFileOutputStream(infoFile); + info.writeBytes(fos); + } catch (DataFormatException dfe) { + _log.error("Error rebuilding the router information", dfe); + } catch (IOException ioe) { + _log.error("Error writing out the rebuilt router information", ioe); + } finally { + if (fos != null) try { fos.close(); } catch (IOException ioe) {} + } } } } diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index e1f87e077ded8c1235896b49923811522eadbbfe..8ab24107c98197555eefc67083d312bbe5d8ab93 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 16; + public final static long BUILD = 17; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java b/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java index 36b989bc7761609ab28b9bf3d83a3b994432d27a..011152caf0f0d3d3c446897eba106cd53f6dec5c 100644 --- a/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java +++ b/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java @@ -31,7 +31,7 @@ import net.i2p.util.SecureFileOutputStream; public class CreateRouterInfoJob extends JobImpl { private static Log _log = new Log(CreateRouterInfoJob.class); - private Job _next; + private final Job _next; public CreateRouterInfoJob(RouterContext ctx, Job next) { super(ctx); @@ -43,10 +43,15 @@ public class CreateRouterInfoJob extends JobImpl { public void runJob() { _log.debug("Creating the new router info"); // create a new router info and store it where LoadRouterInfoJob looks - createRouterInfo(); + synchronized (getContext().router().routerInfoFileLock) { + createRouterInfo(); + } getContext().jobQueue().addJob(_next); } + /** + * Caller must hold Router.routerInfoFileLock + */ RouterInfo createRouterInfo() { RouterInfo info = new RouterInfo(); FileOutputStream fos1 = null; @@ -78,6 +83,9 @@ public class CreateRouterInfoJob extends JobImpl { info.setIdentity(ident); info.sign(signingPrivKey); + + if (!info.isValid()) + throw new DataFormatException("RouterInfo we just built is invalid: " + info); String infoFilename = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT); File ifile = new File(getContext().getRouterDir(), infoFilename); diff --git a/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java b/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java index 94b4f1d2eda8bc2227827cd91ae2299b4ba6c48a..9b484fc5ce3a96c3051ed0c4687808e4fb9a0f3c 100644 --- a/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java +++ b/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java @@ -24,7 +24,7 @@ import net.i2p.router.RouterContext; import net.i2p.util.Log; public class LoadRouterInfoJob extends JobImpl { - private Log _log; + private final Log _log; private boolean _keysExist; private boolean _infoExists; private RouterInfo _us; @@ -37,7 +37,9 @@ public class LoadRouterInfoJob extends JobImpl { public String getName() { return "Load Router Info"; } public void runJob() { - loadRouterInfo(); + synchronized (getContext().router().routerInfoFileLock) { + loadRouterInfo(); + } if (_us == null) { RebuildRouterInfoJob r = new RebuildRouterInfoJob(getContext()); r.rebuildRouterInfo(false); @@ -78,7 +80,11 @@ public class LoadRouterInfoJob extends JobImpl { fis1 = new FileInputStream(rif); info = new RouterInfo(); info.readBytes(fis1); - _log.debug("Reading in routerInfo from " + rif.getAbsolutePath() + " and it has " + info.getAddresses().size() + " addresses"); + // Catch this here before it all gets worse + if (!info.isValid()) + throw new DataFormatException("Our RouterInfo has a bad signature"); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Reading in routerInfo from " + rif.getAbsolutePath() + " and it has " + info.getAddresses().size() + " addresses"); _us = info; } diff --git a/router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java b/router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java index b417c32bbb3343ed72f34dae41f0d7399a32343c..045542a1a43167ad79d4be11c1d37a6164095cd1 100644 --- a/router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java +++ b/router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java @@ -45,7 +45,7 @@ import net.i2p.util.SecureFileOutputStream; * */ public class RebuildRouterInfoJob extends JobImpl { - private Log _log; + private final Log _log; private final static long REBUILD_DELAY = 45*1000; // every 30 seconds @@ -133,17 +133,24 @@ public class RebuildRouterInfoJob extends JobImpl { _log.log(Log.CRIT, "Error rebuilding the new router info", dfe); return; } - + + if (!info.isValid()) { + _log.log(Log.CRIT, "RouterInfo we just built is invalid: " + info, new Exception()); + return; + } + FileOutputStream fos = null; - try { - fos = new SecureFileOutputStream(infoFile); - info.writeBytes(fos); - } catch (DataFormatException dfe) { - _log.log(Log.CRIT, "Error rebuilding the router information", dfe); - } catch (IOException ioe) { - _log.log(Log.CRIT, "Error writing out the rebuilt router information", ioe); - } finally { - if (fos != null) try { fos.close(); } catch (IOException ioe) {} + synchronized (getContext().router().routerInfoFileLock) { + try { + fos = new SecureFileOutputStream(infoFile); + info.writeBytes(fos); + } catch (DataFormatException dfe) { + _log.log(Log.CRIT, "Error rebuilding the router information", dfe); + } catch (IOException ioe) { + _log.log(Log.CRIT, "Error writing out the rebuilt router information", ioe); + } finally { + if (fos != null) try { fos.close(); } catch (IOException ioe) {} + } } } else {