From: Dwight Engen Date: Wed, 11 Sep 2013 22:16:15 +0000 (-0400) Subject: hash lxcname for use in monitor unix socket sun_path[108] X-Git-Tag: lxc-1.0.0.alpha2~129 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b45c701178cdc705d26c95f31035c39bab9edf20;p=thirdparty%2Flxc.git hash lxcname for use in monitor unix socket sun_path[108] - Also convert to unix abstract socket - A simple FNV hash is used instead of SHA-1 since we may not HAVE_GNUTLS Signed-off-by: Dwight Engen Signed-off-by: Serge Hallyn --- diff --git a/src/lxc/monitor.c b/src/lxc/monitor.c index bdcc581c6..64e9987fc 100644 --- a/src/lxc/monitor.c +++ b/src/lxc/monitor.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -123,38 +125,56 @@ int lxc_monitor_close(int fd) return close(fd); } +/* Note we don't use SHA-1 here as we don't want to depend on HAVE_GNUTLS. + * FNV has good anti collision properties and we're not worried + * about pre-image resistance or one-way-ness, we're just trying to make + * the name unique in the 108 bytes of space we have. + */ +#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL) +static uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval) +{ + unsigned char *bp; + + for(bp = buf; bp < (unsigned char *)buf + len; bp++) + { + /* xor the bottom with the current octet */ + hval ^= (uint64_t)*bp; + + /* gcc optimised: + * multiply by the 64 bit FNV magic prime mod 2^64 + */ + hval += (hval << 1) + (hval << 4) + (hval << 5) + + (hval << 7) + (hval << 8) + (hval << 40); + } + + return hval; +} + int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr) { size_t len; int ret; - char *sockname = &addr->sun_path[0]; // 1 for abstract - const char *rundir; + char *sockname = &addr->sun_path[1]; + char path[PATH_MAX+18]; + uint64_t hash; - /* addr.sun_path is only 108 bytes. - * should we take a hash of lxcpath? a subset of it? ftok()? we need - * to make sure it is unique. + /* addr.sun_path is only 108 bytes, so we hash the full name and + * then append as much of the name as we can fit. */ memset(addr, 0, sizeof(*addr)); addr->sun_family = AF_UNIX; len = sizeof(addr->sun_path) - 1; - rundir = get_rundir(); - ret = snprintf(sockname, len, "%s/lxc/%s", rundir, lxcpath); - if (ret < 0 || ret >= len) { - ERROR("rundir/lxcpath (%s/%s) too long for monitor unix socket", rundir, lxcpath); + ret = snprintf(path, sizeof(path), "lxc/%s/monitor-sock", lxcpath); + if (ret < 0 || ret >= sizeof(path)) { + ERROR("lxcpath %s too long for monitor unix socket", lxcpath); return -1; } - process_lock(); - ret = mkdir_p(sockname, 0755); - process_unlock(); - if (ret < 0) { - ERROR("unable to create monitor sock %s", sockname); - return ret; - } - ret = snprintf(sockname, len, "%s/lxc/%s/monitor-sock", rundir, lxcpath); - if (ret < 0 || ret >= len) { - ERROR("rundir/lxcpath (%s/%s) too long for monitor unix socket", rundir, lxcpath); + hash = fnv_64a_buf(path, ret, FNV1A_64_INIT); + ret = snprintf(sockname, len, "lxc/%016" PRIx64 "/%s", hash, lxcpath); + if (ret < 0) return -1; - } + sockname[sizeof(addr->sun_path)-2] = '\0'; + INFO("using monitor sock name %s", sockname); return 0; }