diff options
author | Filipe Coelho <falktx@falktx.com> | 2017-09-15 13:54:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-15 13:54:22 +0200 |
commit | c44a220fbe5775653fc981334ae3d2cfffddc421 (patch) | |
tree | 03a55739e525b0bfe016460d9b62259c49740852 | |
parent | 929009dd39c4f7881840c41eb47cf311284ab324 (diff) | |
parent | d4f925c2eafa050f2cda5b682f077b892d3b3de2 (diff) | |
download | jack2-c44a220fbe5775653fc981334ae3d2cfffddc421.tar.gz |
Merge pull request #257 from sdrik/pull/promiscuous-v2
Secure promiscuous mode
-rw-r--r-- | common/promiscuous.c | 95 | ||||
-rw-r--r-- | common/promiscuous.h | 39 | ||||
-rw-r--r-- | common/shm.c | 6 | ||||
-rw-r--r-- | common/wscript | 3 | ||||
-rw-r--r-- | linux/JackLinuxFutex.cpp | 17 | ||||
-rw-r--r-- | linux/JackLinuxFutex.h | 5 | ||||
-rw-r--r-- | posix/JackPosixSemaphore.cpp | 22 | ||||
-rw-r--r-- | posix/JackPosixSemaphore.h | 7 | ||||
-rw-r--r-- | posix/JackSocket.cpp | 28 | ||||
-rw-r--r-- | posix/JackSocket.h | 10 |
10 files changed, 217 insertions, 15 deletions
diff --git a/common/promiscuous.c b/common/promiscuous.c new file mode 100644 index 00000000..aa6850c1 --- /dev/null +++ b/common/promiscuous.c @@ -0,0 +1,95 @@ +/* + Copyright (C) 2014-2017 Cédric Schieli + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef WIN32 +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <grp.h> +#ifdef __APPLE__ +#include <AvailabilityMacros.h> +#endif +#include "JackError.h" +#endif + + +int +jack_group2gid(const char* group) +{ +#ifdef WIN32 + return -1; +#else + size_t buflen; + char *buf; + int ret; + struct group grp; + struct group *result; + + if (!group || !*group) + return -1; + + ret = strtol(group, &buf, 10); + if (!*buf) + return ret; + +/* MacOSX only defines _SC_GETGR_R_SIZE_MAX starting from 10.4 */ +#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4 + buflen = 4096; +#else + buflen = sysconf(_SC_GETGR_R_SIZE_MAX); + if (buflen == -1) + buflen = 4096; +#endif + buf = (char*)malloc(buflen); + + while (buf && ((ret = getgrnam_r(group, &grp, buf, buflen, &result)) == ERANGE)) { + buflen *= 2; + buf = (char*)realloc(buf, buflen); + } + if (!buf) + return -1; + free(buf); + if (ret || !result) + return -1; + return grp.gr_gid; +#endif +} + +#ifndef WIN32 +int +jack_promiscuous_perms(int fd, const char* path, gid_t gid) +{ + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + if (gid >= 0) { + if (((fd < 0) ? chown(path, -1, gid) : fchown(fd, -1, gid)) < 0) { + jack_log("Cannot chgrp %s: %s. Falling back to permissive perms.", path, strerror(errno)); + } else { + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + } + } + if (((fd < 0) ? chmod(path, mode) : fchmod(fd, mode)) < 0) { + jack_log("Cannot chmod %s: %s. Falling back to default (umask) perms.", path, strerror(errno)); + return -1; + } + return 0; +} +#endif diff --git a/common/promiscuous.h b/common/promiscuous.h new file mode 100644 index 00000000..437fc03c --- /dev/null +++ b/common/promiscuous.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2014-2017 Cédric Schieli + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef __jack_gid_h__ +#define __jack_gid_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +int jack_group2gid (const char *group); /*!< Lookup gid for a UNIX group in a thread-safe way */ +#ifndef WIN32 +int jack_promiscuous_perms (int fd, const char *path, gid_t gid); /*!< Set promiscuous permissions on object referenced by fd and/or path */ +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_gid_h__ */ + + diff --git a/common/shm.c b/common/shm.c index 75075743..067ef3fe 100644 --- a/common/shm.c +++ b/common/shm.c @@ -52,6 +52,7 @@ #include <sys/shm.h> #include <sys/sem.h> #include <stdlib.h> +#include "promiscuous.h" #endif @@ -837,6 +838,7 @@ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si) int shm_fd; int rc = -1; char name[SHM_NAME_MAX+1]; + const char* promiscuous; if (jack_shm_lock_registry () < 0) { jack_error ("jack_shm_lock_registry fails..."); @@ -877,6 +879,10 @@ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si) goto unlock; } + promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); + if ((promiscuous != NULL) && (jack_promiscuous_perms(shm_fd, name, jack_group2gid(promiscuous)) < 0)) + goto unlock; + close (shm_fd); registry->size = size; strncpy (registry->id, name, sizeof (registry->id)); diff --git a/common/wscript b/common/wscript index 081f6b71..60874720 100644 --- a/common/wscript +++ b/common/wscript @@ -80,6 +80,7 @@ def build(bld): common_libsources += [ 'JackDebugClient.cpp', 'timestamps.c', + 'promiscuous.c', '../posix/JackPosixThread.cpp', '../posix/JackPosixProcessSync.cpp', '../posix/JackPosixMutex.cpp', @@ -95,6 +96,7 @@ def build(bld): common_libsources += [ 'JackDebugClient.cpp', 'timestamps.c', + 'promiscuous.c', '../posix/JackPosixThread.cpp', '../posix/JackFifo.cpp', '../posix/JackPosixProcessSync.cpp', @@ -109,6 +111,7 @@ def build(bld): common_libsources += [ 'JackDebugClient.cpp', 'timestamps.c', + 'promiscuous.c', '../posix/JackPosixProcessSync.cpp', '../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', diff --git a/linux/JackLinuxFutex.cpp b/linux/JackLinuxFutex.cpp index 6e897bc8..b724f191 100644 --- a/linux/JackLinuxFutex.cpp +++ b/linux/JackLinuxFutex.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackTools.h" #include "JackConstants.h" #include "JackError.h" +#include "promiscuous.h" #include <fcntl.h> #include <stdio.h> #include <sys/mman.h> @@ -31,11 +32,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. namespace Jack { +JackLinuxFutex::JackLinuxFutex() : JackSynchro(), fSharedMem(-1), fFutex(NULL), fPrivate(false) +{ + const char* promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); + fPromiscuous = (promiscuous != NULL); + fPromiscuousGid = jack_group2gid(promiscuous); +} + void JackLinuxFutex::BuildName(const char* client_name, const char* server_name, char* res, int size) { char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; JackTools::RewriteName(client_name, ext_client_name); - if (getenv("JACK_PROMISCUOUS_SERVER")) { + if (fPromiscuous) { snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); } else { snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); @@ -132,6 +140,13 @@ bool JackLinuxFutex::Allocate(const char* name, const char* server_name, int val ftruncate(fSharedMem, sizeof(FutexData)); + if (fPromiscuous && (jack_promiscuous_perms(fSharedMem, fName, fPromiscuousGid) < 0)) { + close(fSharedMem); + fSharedMem = -1; + shm_unlink(fName); + return false; + } + if ((fFutex = (FutexData*)mmap(NULL, sizeof(FutexData), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fSharedMem, 0)) == NULL) { jack_error("Allocate: can't check in named futex name = %s err = %s", fName, strerror(errno)); close(fSharedMem); diff --git a/linux/JackLinuxFutex.h b/linux/JackLinuxFutex.h index 5c8a7006..559f1e63 100644 --- a/linux/JackLinuxFutex.h +++ b/linux/JackLinuxFutex.h @@ -53,6 +53,8 @@ class SERVER_EXPORT JackLinuxFutex : public detail::JackSynchro int fSharedMem; FutexData* fFutex; bool fPrivate; + bool fPromiscuous; + int fPromiscuousGid; protected: @@ -60,8 +62,7 @@ class SERVER_EXPORT JackLinuxFutex : public detail::JackSynchro public: - JackLinuxFutex():JackSynchro(), fSharedMem(-1), fFutex(NULL), fPrivate(false) - {} + JackLinuxFutex(); bool Signal(); bool SignalAll(); diff --git a/posix/JackPosixSemaphore.cpp b/posix/JackPosixSemaphore.cpp index 9e511647..1f4df7a4 100644 --- a/posix/JackPosixSemaphore.cpp +++ b/posix/JackPosixSemaphore.cpp @@ -24,10 +24,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <fcntl.h> #include <stdio.h> #include <sys/time.h> +#ifdef __linux__ +#include "promiscuous.h" +#endif namespace Jack { +JackPosixSemaphore::JackPosixSemaphore() : JackSynchro(), fSemaphore(NULL) +{ + const char* promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); + fPromiscuous = (promiscuous != NULL); +#ifdef __linux__ + fPromiscuousGid = jack_group2gid(promiscuous); +#endif +} + void JackPosixSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size) { char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; @@ -35,7 +47,7 @@ void JackPosixSemaphore::BuildName(const char* client_name, const char* server_n #if __APPLE__ // POSIX semaphore names are limited to 32 characters... snprintf(res, 32, "js_%s", ext_client_name); #else - if (getenv("JACK_PROMISCUOUS_SERVER")) { + if (fPromiscuous) { snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); } else { snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); @@ -147,6 +159,14 @@ bool JackPosixSemaphore::Allocate(const char* name, const char* server_name, int jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); return false; } else { +#ifdef __linux__ + if (fPromiscuous) { + char sempath[SYNC_MAX_NAME_SIZE+13]; + snprintf(sempath, sizeof(sempath), "/dev/shm/sem.%s", fName); + if (jack_promiscuous_perms(-1, sempath, fPromiscuousGid) < 0) + return false; + } +#endif return true; } } diff --git a/posix/JackPosixSemaphore.h b/posix/JackPosixSemaphore.h index 94f4d60f..bc5e0cea 100644 --- a/posix/JackPosixSemaphore.h +++ b/posix/JackPosixSemaphore.h @@ -39,6 +39,10 @@ class SERVER_EXPORT JackPosixSemaphore : public detail::JackSynchro private: sem_t* fSemaphore; + bool fPromiscuous; +#ifdef __linux__ + int fPromiscuousGid; +#endif protected: @@ -46,8 +50,7 @@ class SERVER_EXPORT JackPosixSemaphore : public detail::JackSynchro public: - JackPosixSemaphore():JackSynchro(), fSemaphore(NULL) - {} + JackPosixSemaphore(); bool Signal(); bool SignalAll(); diff --git a/posix/JackSocket.cpp b/posix/JackSocket.cpp index e8b528d9..73f1fc44 100644 --- a/posix/JackSocket.cpp +++ b/posix/JackSocket.cpp @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackConstants.h" #include "JackTools.h" #include "JackError.h" +#include "promiscuous.h" #include <string.h> #include <stdio.h> #include <pthread.h> @@ -29,18 +30,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. namespace Jack { -static void BuildName(const char* client_name, char* res, const char* dir, int which, int size) +static void BuildName(const char* client_name, char* res, const char* dir, int which, int size, bool promiscuous) { char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; JackTools::RewriteName(client_name, ext_client_name); - if (getenv("JACK_PROMISCUOUS_SERVER")) { + if (promiscuous) { snprintf(res, size, "%s/jack_%s_%d", dir, ext_client_name, which); } else { snprintf(res, size, "%s/jack_%s_%d_%d", dir, ext_client_name, JackTools::GetUID(), which); } } -JackClientSocket::JackClientSocket(int socket): JackClientRequestInterface(), fSocket(socket),fTimeOut(0) +JackClientSocket::JackClientSocket(): JackClientRequestInterface(), fSocket(-1), fTimeOut(0) +{ + const char* promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); + fPromiscuous = (promiscuous != NULL); + fPromiscuousGid = jack_group2gid(promiscuous); +} + +JackClientSocket::JackClientSocket(int socket): JackClientRequestInterface(), fSocket(socket),fTimeOut(0), fPromiscuous(false), fPromiscuousGid(-1) {} #if defined(__sun__) || defined(sun) @@ -123,7 +131,7 @@ int JackClientSocket::Connect(const char* dir, const char* name, int which) // A } addr.sun_family = AF_UNIX; - BuildName(name, addr.sun_path, dir, which, sizeof(addr.sun_path)); + BuildName(name, addr.sun_path, dir, which, sizeof(addr.sun_path), fPromiscuous); jack_log("JackClientSocket::Connect : addr.sun_path %s", addr.sun_path); if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { @@ -247,6 +255,13 @@ int JackClientSocket::Write(void* data, int len) } } +JackServerSocket::JackServerSocket(): fSocket( -1) +{ + const char* promiscuous = getenv("JACK_PROMISCUOUS_SERVER"); + fPromiscuous = (promiscuous != NULL); + fPromiscuousGid = jack_group2gid(promiscuous); +} + int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which" { struct sockaddr_un addr; @@ -258,7 +273,7 @@ int JackServerSocket::Bind(const char* dir, const char* name, int which) // A re addr.sun_family = AF_UNIX; // Socket name has to be kept in fName to be "unlinked". - BuildName(name, fName, dir, which, sizeof(addr.sun_path)); + BuildName(name, fName, dir, which, sizeof(addr.sun_path), fPromiscuous); strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1); jack_log("JackServerSocket::Bind : addr.sun_path %s", addr.sun_path); @@ -274,6 +289,9 @@ int JackServerSocket::Bind(const char* dir, const char* name, int which) // A re goto error; } + if (fPromiscuous && (jack_promiscuous_perms(-1, fName, fPromiscuousGid) < 0)) + goto error; + return 0; error: diff --git a/posix/JackSocket.h b/posix/JackSocket.h index 8568025b..5f0501a1 100644 --- a/posix/JackSocket.h +++ b/posix/JackSocket.h @@ -45,11 +45,12 @@ class JackClientSocket : public detail::JackClientRequestInterface int fSocket; int fTimeOut; + bool fPromiscuous; + int fPromiscuousGid; public: - JackClientSocket():JackClientRequestInterface(), fSocket(-1), fTimeOut(0) - {} + JackClientSocket(); JackClientSocket(int socket); int Connect(const char* dir, const char* name, int which); @@ -80,11 +81,12 @@ class JackServerSocket int fSocket; char fName[SOCKET_MAX_NAME_SIZE]; + bool fPromiscuous; + int fPromiscuousGid; public: - JackServerSocket(): fSocket( -1) - {} + JackServerSocket(); ~JackServerSocket() {} |