summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipe Coelho <falktx@falktx.com>2017-09-15 13:54:22 +0200
committerGitHub <noreply@github.com>2017-09-15 13:54:22 +0200
commitc44a220fbe5775653fc981334ae3d2cfffddc421 (patch)
tree03a55739e525b0bfe016460d9b62259c49740852
parent929009dd39c4f7881840c41eb47cf311284ab324 (diff)
parentd4f925c2eafa050f2cda5b682f077b892d3b3de2 (diff)
downloadjack2-c44a220fbe5775653fc981334ae3d2cfffddc421.tar.gz
Merge pull request #257 from sdrik/pull/promiscuous-v2
Secure promiscuous mode
-rw-r--r--common/promiscuous.c95
-rw-r--r--common/promiscuous.h39
-rw-r--r--common/shm.c6
-rw-r--r--common/wscript3
-rw-r--r--linux/JackLinuxFutex.cpp17
-rw-r--r--linux/JackLinuxFutex.h5
-rw-r--r--posix/JackPosixSemaphore.cpp22
-rw-r--r--posix/JackPosixSemaphore.h7
-rw-r--r--posix/JackSocket.cpp28
-rw-r--r--posix/JackSocket.h10
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()
{}