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
| @@ -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 | |||
| } | |||
| @@ -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__ */ | |||
| @@ -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)); | |||
| @@ -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', | |||
| @@ -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; | |||
| } | |||
| } | |||
| @@ -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(); | |||
| @@ -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: | |||
| @@ -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() | |||
| {} | |||