Browse Source

Merge pull request #257 from sdrik/pull/promiscuous-v2

Secure promiscuous mode
tags/v1.9.12
Filipe Coelho GitHub 8 years ago
parent
commit
c44a220fbe
10 changed files with 217 additions and 15 deletions
  1. +95
    -0
      common/promiscuous.c
  2. +39
    -0
      common/promiscuous.h
  3. +6
    -0
      common/shm.c
  4. +3
    -0
      common/wscript
  5. +16
    -1
      linux/JackLinuxFutex.cpp
  6. +3
    -2
      linux/JackLinuxFutex.h
  7. +21
    -1
      posix/JackPosixSemaphore.cpp
  8. +5
    -2
      posix/JackPosixSemaphore.h
  9. +23
    -5
      posix/JackSocket.cpp
  10. +6
    -4
      posix/JackSocket.h

+ 95
- 0
common/promiscuous.c View File

@@ -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

+ 39
- 0
common/promiscuous.h View File

@@ -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__ */



+ 6
- 0
common/shm.c View File

@@ -52,6 +52,7 @@
#include <sys/shm.h> #include <sys/shm.h>
#include <sys/sem.h> #include <sys/sem.h>
#include <stdlib.h> #include <stdlib.h>
#include "promiscuous.h"


#endif #endif


@@ -837,6 +838,7 @@ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
int shm_fd; int shm_fd;
int rc = -1; int rc = -1;
char name[SHM_NAME_MAX+1]; char name[SHM_NAME_MAX+1];
const char* promiscuous;


if (jack_shm_lock_registry () < 0) { if (jack_shm_lock_registry () < 0) {
jack_error ("jack_shm_lock_registry fails..."); 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; 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); close (shm_fd);
registry->size = size; registry->size = size;
strncpy (registry->id, name, sizeof (registry->id)); strncpy (registry->id, name, sizeof (registry->id));


+ 3
- 0
common/wscript View File

@@ -80,6 +80,7 @@ def build(bld):
common_libsources += [ common_libsources += [
'JackDebugClient.cpp', 'JackDebugClient.cpp',
'timestamps.c', 'timestamps.c',
'promiscuous.c',
'../posix/JackPosixThread.cpp', '../posix/JackPosixThread.cpp',
'../posix/JackPosixProcessSync.cpp', '../posix/JackPosixProcessSync.cpp',
'../posix/JackPosixMutex.cpp', '../posix/JackPosixMutex.cpp',
@@ -95,6 +96,7 @@ def build(bld):
common_libsources += [ common_libsources += [
'JackDebugClient.cpp', 'JackDebugClient.cpp',
'timestamps.c', 'timestamps.c',
'promiscuous.c',
'../posix/JackPosixThread.cpp', '../posix/JackPosixThread.cpp',
'../posix/JackFifo.cpp', '../posix/JackFifo.cpp',
'../posix/JackPosixProcessSync.cpp', '../posix/JackPosixProcessSync.cpp',
@@ -109,6 +111,7 @@ def build(bld):
common_libsources += [ common_libsources += [
'JackDebugClient.cpp', 'JackDebugClient.cpp',
'timestamps.c', 'timestamps.c',
'promiscuous.c',
'../posix/JackPosixProcessSync.cpp', '../posix/JackPosixProcessSync.cpp',
'../posix/JackPosixThread.cpp', '../posix/JackPosixThread.cpp',
'../posix/JackPosixMutex.cpp', '../posix/JackPosixMutex.cpp',


+ 16
- 1
linux/JackLinuxFutex.cpp View File

@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackTools.h" #include "JackTools.h"
#include "JackConstants.h" #include "JackConstants.h"
#include "JackError.h" #include "JackError.h"
#include "promiscuous.h"
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <sys/mman.h> #include <sys/mman.h>
@@ -31,11 +32,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
namespace Jack 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) void JackLinuxFutex::BuildName(const char* client_name, const char* server_name, char* res, int size)
{ {
char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; char ext_client_name[SYNC_MAX_NAME_SIZE + 1];
JackTools::RewriteName(client_name, ext_client_name); 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); snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name);
} else { } else {
snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); 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)); 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) { 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)); jack_error("Allocate: can't check in named futex name = %s err = %s", fName, strerror(errno));
close(fSharedMem); close(fSharedMem);


+ 3
- 2
linux/JackLinuxFutex.h View File

@@ -53,6 +53,8 @@ class SERVER_EXPORT JackLinuxFutex : public detail::JackSynchro
int fSharedMem; int fSharedMem;
FutexData* fFutex; FutexData* fFutex;
bool fPrivate; bool fPrivate;
bool fPromiscuous;
int fPromiscuousGid;


protected: protected:


@@ -60,8 +62,7 @@ class SERVER_EXPORT JackLinuxFutex : public detail::JackSynchro


public: public:


JackLinuxFutex():JackSynchro(), fSharedMem(-1), fFutex(NULL), fPrivate(false)
{}
JackLinuxFutex();


bool Signal(); bool Signal();
bool SignalAll(); bool SignalAll();


+ 21
- 1
posix/JackPosixSemaphore.cpp View File

@@ -24,10 +24,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <sys/time.h>
#ifdef __linux__
#include "promiscuous.h"
#endif


namespace Jack 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) void JackPosixSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size)
{ {
char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; 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... #if __APPLE__ // POSIX semaphore names are limited to 32 characters...
snprintf(res, 32, "js_%s", ext_client_name); snprintf(res, 32, "js_%s", ext_client_name);
#else #else
if (getenv("JACK_PROMISCUOUS_SERVER")) {
if (fPromiscuous) {
snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name);
} else { } else {
snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); 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)); jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno));
return false; return false;
} else { } 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; return true;
} }
} }


+ 5
- 2
posix/JackPosixSemaphore.h View File

@@ -39,6 +39,10 @@ class SERVER_EXPORT JackPosixSemaphore : public detail::JackSynchro
private: private:


sem_t* fSemaphore; sem_t* fSemaphore;
bool fPromiscuous;
#ifdef __linux__
int fPromiscuousGid;
#endif


protected: protected:


@@ -46,8 +50,7 @@ class SERVER_EXPORT JackPosixSemaphore : public detail::JackSynchro


public: public:


JackPosixSemaphore():JackSynchro(), fSemaphore(NULL)
{}
JackPosixSemaphore();


bool Signal(); bool Signal();
bool SignalAll(); bool SignalAll();


+ 23
- 5
posix/JackSocket.cpp View File

@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackConstants.h" #include "JackConstants.h"
#include "JackTools.h" #include "JackTools.h"
#include "JackError.h" #include "JackError.h"
#include "promiscuous.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <pthread.h> #include <pthread.h>
@@ -29,18 +30,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
namespace Jack 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]; char ext_client_name[SYNC_MAX_NAME_SIZE + 1];
JackTools::RewriteName(client_name, ext_client_name); 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); snprintf(res, size, "%s/jack_%s_%d", dir, ext_client_name, which);
} else { } else {
snprintf(res, size, "%s/jack_%s_%d_%d", dir, ext_client_name, JackTools::GetUID(), which); 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) #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; 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); jack_log("JackClientSocket::Connect : addr.sun_path %s", addr.sun_path);


if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { 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" int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which"
{ {
struct sockaddr_un addr; 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; addr.sun_family = AF_UNIX;
// Socket name has to be kept in fName to be "unlinked". // 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); strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1);
jack_log("JackServerSocket::Bind : addr.sun_path %s", addr.sun_path); 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; goto error;
} }


if (fPromiscuous && (jack_promiscuous_perms(-1, fName, fPromiscuousGid) < 0))
goto error;

return 0; return 0;


error: error:


+ 6
- 4
posix/JackSocket.h View File

@@ -45,11 +45,12 @@ class JackClientSocket : public detail::JackClientRequestInterface


int fSocket; int fSocket;
int fTimeOut; int fTimeOut;
bool fPromiscuous;
int fPromiscuousGid;


public: public:


JackClientSocket():JackClientRequestInterface(), fSocket(-1), fTimeOut(0)
{}
JackClientSocket();
JackClientSocket(int socket); JackClientSocket(int socket);


int Connect(const char* dir, const char* name, int which); int Connect(const char* dir, const char* name, int which);
@@ -80,11 +81,12 @@ class JackServerSocket


int fSocket; int fSocket;
char fName[SOCKET_MAX_NAME_SIZE]; char fName[SOCKET_MAX_NAME_SIZE];
bool fPromiscuous;
int fPromiscuousGid;


public: public:


JackServerSocket(): fSocket( -1)
{}
JackServerSocket();
~JackServerSocket() ~JackServerSocket()
{} {}




Loading…
Cancel
Save