diff options
author | markus@chromium.org <markus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-11 21:46:07 +0000 |
---|---|---|
committer | markus@chromium.org <markus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-11 21:46:07 +0000 |
commit | 0fb2bd939380e4d46bad10eb597bff4980ca7db2 (patch) | |
tree | 79d017b24dfb4d91059b856da7b8ad43764d76e6 /sandbox/linux/seccomp/mutex.h | |
parent | 135b165d2bca7a9a7302eb4f771dc713c8100edb (diff) | |
download | chromium_src-0fb2bd939380e4d46bad10eb597bff4980ca7db2.zip chromium_src-0fb2bd939380e4d46bad10eb597bff4980ca7db2.tar.gz chromium_src-0fb2bd939380e4d46bad10eb597bff4980ca7db2.tar.bz2 |
Initial version of the Seccomp sandbox. Imported from http://code.google.com/p/seccompsandbox/
Make the seccomp sandbox dependant on the --enable-seccomp-sandbox flag
Review URL: http://codereview.chromium.org/165310
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23087 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/linux/seccomp/mutex.h')
-rw-r--r-- | sandbox/linux/seccomp/mutex.h | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/sandbox/linux/seccomp/mutex.h b/sandbox/linux/seccomp/mutex.h new file mode 100644 index 0000000..7729be6 --- /dev/null +++ b/sandbox/linux/seccomp/mutex.h @@ -0,0 +1,149 @@ +#ifndef MUTEX_H__ +#define MUTEX_H__ + +#include "sandbox_impl.h" + +namespace playground { + +class Mutex { + public: + typedef int mutex_t; + + enum { kInitValue = 0 }; + + static void initMutex(mutex_t* mutex) { + // Mutex is unlocked, and nobody is waiting for it + *mutex = kInitValue; + } + + static void unlockMutex(mutex_t* mutex) { + char status; + #if defined(__x86_64__) || defined(__i386__) + asm volatile( + "lock; addl %2, %0\n" + "setz %1" + : "=m"(*mutex), "=qm"(status) + : "ir"(0x80000000), "m"(*mutex)); + #else + #error Unsupported target platform + #endif + if (status) { + // Mutex is zero now. No other waiters. So, we can return. + return; + } + // We unlocked the mutex, but still need to wake up other waiters. + Sandbox::SysCalls sys; + sys.futex(mutex, FUTEX_WAKE, 1, NULL); + } + + static bool lockMutex(mutex_t* mutex, int timeout = 0) { + bool rc = true; + // Increment mutex to add ourselves to the list of waiters + #if defined(__x86_64__) || defined(__i386__) + asm volatile( + "lock; incl %0\n" + : "=m"(*mutex) + : "m"(*mutex)); + #else + #error Unsupported target platform + #endif + for (;;) { + // Atomically check whether the mutex is available and if so, acquire it + char status; + #if defined(__x86_64__) || defined(__i386__) + asm volatile( + "lock; btsl %3, %1\n" + "setc %0" + : "=q"(status), "=m"(*mutex) + : "m"(*mutex), "ir"(31)); + #else + #error Unsupported target platform + #endif + if (!status) { + done: + // If the mutex was available, remove ourselves from list of waiters + #if defined(__x86_64__) || defined(__i386__) + asm volatile( + "lock; decl %0\n" + : "=m"(*mutex) + : "m"(*mutex)); + #else + #error Unsupported target platform + #endif + return rc; + } + int value = *mutex; + if (value >= 0) { + // Mutex has just become available, no need to call kernel + continue; + } + Sandbox::SysCalls sys; + Sandbox::SysCalls::kernel_timespec tm; + if (timeout) { + tm.tv_sec = timeout / 1000; + tm.tv_nsec = (timeout % 1000) * 1000 * 1000; + } else { + tm.tv_sec = 0; + tm.tv_nsec = 0; + } + if (NOINTR_SYS(sys.futex(mutex, FUTEX_WAIT, value, &tm)) && + sys.my_errno == ETIMEDOUT) { + rc = false; + goto done; + } + } + } + + static bool waitForUnlock(mutex_t* mutex, int timeout = 0) { + bool rc = true; + // Increment mutex to add ourselves to the list of waiters + #if defined(__x86_64__) || defined(__i386__) + asm volatile( + "lock; incl %0\n" + : "=m"(*mutex) + : "m"(*mutex)); + #else + #error Unsupported target platform + #endif + Sandbox::SysCalls sys; + for (;;) { + mutex_t value = *mutex; + if (value >= 0) { + done: + // Mutex was not locked. Remove ourselves from list of waiters, notify + // any other waiters (if any), and return. + #if defined(__x86_64__) || defined(__i386__) + asm volatile( + "lock; decl %0\n" + : "=m"(*mutex) + : "m"(*mutex)); + #else + #error Unsupported target platform + #endif + NOINTR_SYS(sys.futex(mutex, FUTEX_WAKE, 1, 0)); + return rc; + } + + // Wait for mutex to become unlocked + Sandbox::SysCalls::kernel_timespec tm; + if (timeout) { + tm.tv_sec = timeout / 1000; + tm.tv_nsec = (timeout % 1000) * 1000 * 1000; + } else { + tm.tv_sec = 0; + tm.tv_nsec = 0; + } + + if (NOINTR_SYS(sys.futex(mutex, FUTEX_WAIT, value, &tm)) && + sys.my_errno == ETIMEDOUT) { + rc = false; + goto done; + } + } + } + +}; + +} // namespace + +#endif // MUTEX_H__ |