Browse Source

Allow setting group/permissions of filesystem objects in promiscuous mode

If the value of the JACK_PROMISCOUS_SERVER environment variable is set to the
name or gid of a valid UNIX group for the current user, then all filesystem
objects (e.g. sockets, semaphores and shared memory segments) will be created
with this group as owner, and the permissions will be set to 0660. If not, the
permissions will be set to 0666.
This remove the requirement to use a way too permissive umask for promiscuous
mode to work properly.
For that purpose, a new jack_group2gid helper function has been introduced in
its own obj file so it can be called from both C and C++ code.
pull/77/head
Cédric Schieli 11 years ago
parent
commit
8a19dc8823
8 changed files with 195 additions and 12 deletions
  1. +61
    -0
      common/gid.c
  2. +36
    -0
      common/gid.h
  3. +17
    -0
      common/shm.c
  4. +3
    -0
      common/wscript
  5. +31
    -1
      posix/JackPosixSemaphore.cpp
  6. +5
    -2
      posix/JackPosixSemaphore.h
  7. +36
    -5
      posix/JackSocket.cpp
  8. +6
    -4
      posix/JackSocket.h

+ 61
- 0
common/gid.c View File

@@ -0,0 +1,61 @@
/*
Copyright (C) 2014 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 <grp.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;

buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
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
}

+ 36
- 0
common/gid.h View File

@@ -0,0 +1,36 @@
/*
Copyright (C) 2014 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 */

#ifdef __cplusplus
}
#endif

#endif /* __jack_gid_h__ */



+ 17
- 0
common/shm.c View File

@@ -52,6 +52,7 @@
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdlib.h>
#include "gid.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,21 @@ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
goto unlock;
}

if ((promiscuous = getenv("JACK_PROMISCUOUS_SERVER")) != NULL) {
gid_t gid = jack_group2gid(promiscuous);
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
if (gid >= 0) {
if (fchown(shm_fd, -1, gid) < 0) {
jack_log("Cannot chgrp shm segment %s (%s)", name, strerror (errno));
} else {
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
}
}
if (fchmod(shm_fd, mode) < 0) {
jack_log("Cannot chmod shm segment %s (%s)", name, strerror (errno));
}
}

close (shm_fd);
registry->size = size;
strncpy (registry->id, name, sizeof (registry->id));


+ 3
- 0
common/wscript View File

@@ -82,6 +82,7 @@ def build(bld):
common_libsources += [
'JackDebugClient.cpp',
'timestamps.c',
'gid.c',
'../posix/JackPosixThread.cpp',
'../posix/JackPosixProcessSync.cpp',
'../posix/JackPosixMutex.cpp',
@@ -97,6 +98,7 @@ def build(bld):
common_libsources += [
'JackDebugClient.cpp',
'timestamps.c',
'gid.c',
'../posix/JackPosixThread.cpp',
'../posix/JackFifo.cpp',
'../posix/JackPosixProcessSync.cpp',
@@ -111,6 +113,7 @@ def build(bld):
common_libsources += [
'JackDebugClient.cpp',
'timestamps.c',
'gid.c',
'../posix/JackPosixProcessSync.cpp',
'../posix/JackPosixThread.cpp',
'../posix/JackPosixMutex.cpp',


+ 31
- 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 <stdio.h>
#include <sys/time.h>
#ifdef __linux__
#include "gid.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,24 @@ 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);
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
if (fPromiscuousGid >= 0) {
if (chown(sempath, -1, fPromiscuousGid) < 0) {
jack_log("Cannot chgrp semaphore name = %s err = %s, falling back to 0666 mode", sempath, strerror(errno));
} else {
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
}
}
if (chmod(sempath, mode) < 0) {
jack_error("Cannot chmod semaphore name = %s err = %s", sempath, strerror(errno));
return false;
}
}
#endif
return true;
}
}


+ 5
- 2
posix/JackPosixSemaphore.h View File

@@ -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();


+ 36
- 5
posix/JackSocket.cpp View File

@@ -21,26 +21,35 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackConstants.h"
#include "JackTools.h"
#include "JackError.h"
#include "gid.h"
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>

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 +132,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 +256,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 +274,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 +290,21 @@ int JackServerSocket::Bind(const char* dir, const char* name, int which) // A re
goto error;
}

if (fPromiscuous) {
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
if (fPromiscuousGid >= 0) {
if (chown(fName, -1, fPromiscuousGid) < 0) {
jack_log("Cannot chgrp socket %s err = %s, falling back to 0666 mode", fName, strerror(errno));
} else {
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
}
}
if (chmod(fName, mode) < 0) {
jack_error("Cannot chmod socket %s err = %s", fName, strerror(errno));
goto error;
}
}

return 0;

error:


+ 6
- 4
posix/JackSocket.h View File

@@ -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()
{}



Loading…
Cancel
Save