// Get the policy to be applied for the user POLICY *SamGetUserPolicy(HUB *h, char *username) { POLICY *ret = NULL; // Validate arguments if (h == NULL || username == NULL) { return NULL; } AcLock(h); { USER *u; u = AcGetUser(h, username); if (u) { USERGROUP *g = NULL; Lock(u->lock); { if (u->Policy != NULL) { ret = ClonePolicy(u->Policy); } g = u->Group; if (g != NULL) { AddRef(g->ref); } } Unlock(u->lock); ReleaseUser(u); u = NULL; if (ret == NULL) { if (g != NULL) { Lock(g->lock); { ret = ClonePolicy(g->Policy); } Unlock(g->lock); } } if (g != NULL) { ReleaseGroup(g); } } } AcUnlock(h); return ret; }
// Overwrite policy value (If old version data overwrites new version, leave new version value as it is.) void OverwritePolicy(POLICY **target, POLICY *p) { // Validate arguments if (target == NULL) { return; } if (p == NULL) { // Erase policy if (*target != NULL) { Free(*target); *target = NULL; } } else { if (p->Ver3) { // Ver 3 if (*target != NULL) { Free(*target); *target = NULL; } *target = ClonePolicy(p); } else { // Ver 2 if (*target == NULL) { *target = ClonePolicy(p); } else { Copy(*target, p, NUM_POLICY_ITEM_FOR_VER2 * sizeof(UINT)); } } } }
// Get group policy POLICY *GetGroupPolicy(USERGROUP *g) { POLICY *ret; // Validate arguments if (g == NULL) { return NULL; } Lock(g->lock); { if (g->Policy == NULL) { ret = NULL; } else { ret = ClonePolicy(g->Policy); } } Unlock(g->lock); return ret; }
// Get user policy POLICY *GetUserPolicy(USER *u) { POLICY *ret; // Validate arguments if (u == NULL) { return NULL; } Lock(u->lock); { if (u->Policy == NULL) { ret = NULL; } else { ret = ClonePolicy(u->Policy); } } Unlock(u->lock); return ret; }
// Layer-3 interface thread void L3IfThread(THREAD *t, void *param) { L3IF *f; CONNECTION *c; SESSION *s; POLICY *policy; char tmp[MAX_SIZE]; char name[MAX_SIZE]; char username[MAX_SIZE]; // Validate arguments if (t == NULL || param == NULL) { return; } f = (L3IF *)param; StrCpy(username, sizeof(username), L3_USERNAME); if (f->Switch != NULL) { StrCat(username, sizeof(username), f->Switch->Name); } // Create a connection c = NewServerConnection(f->Switch->Cedar, NULL, t); c->Protocol = CONNECTION_HUB_LAYER3; // Create a Session policy = ClonePolicy(GetDefaultPolicy()); // Not to limit the number of broadcast by policy policy->NoBroadcastLimiter = true; s = NewServerSession(f->Switch->Cedar, c, f->Hub, username, policy); c->Session = s; ReleaseConnection(c); // Determine the name of the session GetMachineHostName(tmp, sizeof(tmp)); if (f->Switch->Cedar->Server->ServerType == SERVER_TYPE_STANDALONE) { Format(name, sizeof(name), "SID-L3-%s-%u", f->Switch->Name, Inc(f->Hub->SessionCounter)); } else { Format(name, sizeof(name), "SID-L3-%s-%s-%u", tmp, f->Switch->Name, Inc(f->Hub->SessionCounter)); } ConvertSafeFileName(name, sizeof(name), name); StrUpper(name); Free(s->Name); s->Name = CopyStr(name); s->L3SwitchMode = true; s->L3If = f; if (s->Username != NULL) { Free(s->Username); } s->Username = CopyStr(username); StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username); f->Session = s; AddRef(s->ref); // Notify the initialization completion NoticeThreadInit(t); // Session main process SessionMain(s); // Release the session ReleaseSession(s); }
// Create new local-bridge BRIDGE *BrNewBridge(HUB *h, char *name, POLICY *p, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast, LOCALBRIDGE *parent_local_bridge) { BRIDGE *b; POLICY *policy; THREAD *t; // Validate arguments if (h == NULL || name == NULL || parent_local_bridge == NULL) { return NULL; } if (p == NULL) { policy = ClonePolicy(GetDefaultPolicy()); } else { policy = ClonePolicy(p); } b = ZeroMalloc(sizeof(BRIDGE)); b->Cedar = h->Cedar; b->Hub = h; StrCpy(b->Name, sizeof(b->Name), name); b->Policy = policy; b->Local = local; b->Monitor = monitor; b->TapMode = tapmode; b->LimitBroadcast = limit_broadcast; b->ParentLocalBridge = parent_local_bridge; if (b->TapMode) { if (tapaddr != NULL && IsZero(tapaddr, 6) == false) { Copy(b->TapMacAddress, tapaddr, 6); } else { GenMacAddress(b->TapMacAddress); } } if (monitor) { // Enabling monitoring mode policy->MonitorPort = true; } if (b->LimitBroadcast == false) { // Disable broadcast limiter policy->NoBroadcastLimiter = true; } // Start thread t = NewThread(BrBridgeThread, b); WaitThreadInit(t); ReleaseThread(t); return b; }
virtual ResultExpr EvaluateSyscall(int sysno) const override { switch (sysno) { // Timekeeping case __NR_clock_gettime: { Arg<clockid_t> clk_id(0); return If(clk_id == CLOCK_MONOTONIC, Allow()) .ElseIf(clk_id == CLOCK_REALTIME, Allow()) .Else(InvalidSyscall()); } case __NR_gettimeofday: #ifdef __NR_time case __NR_time: #endif case __NR_nanosleep: return Allow(); // Thread synchronization case __NR_futex: // FIXME: This could be more restrictive.... return Allow(); // Asynchronous I/O case __NR_epoll_wait: case __NR_epoll_pwait: case __NR_epoll_ctl: case __NR_ppoll: case __NR_poll: return Allow(); // Used when requesting a crash dump. case __NR_pipe: return Allow(); // Metadata of opened files CASES_FOR_fstat: return Allow(); // Simple I/O case __NR_write: case __NR_read: case __NR_writev: // see SandboxLogging.cpp return Allow(); // Memory mapping CASES_FOR_mmap: case __NR_munmap: return Allow(); // Signal handling #if defined(ANDROID) || defined(MOZ_ASAN) case __NR_sigaltstack: #endif CASES_FOR_sigreturn: CASES_FOR_sigprocmask: CASES_FOR_sigaction: return Allow(); // Send signals within the process (raise(), profiling, etc.) case __NR_tgkill: { Arg<pid_t> tgid(0); return If(tgid == getpid(), Allow()) .Else(InvalidSyscall()); } #if defined(ANDROID) && ANDROID_VERSION < 16 // Polyfill with tgkill; see above. case __NR_tkill: return Trap(TKillCompatTrap, nullptr); #endif // Yield case __NR_sched_yield: return Allow(); // Thread creation. case __NR_clone: return ClonePolicy(); // More thread creation. #ifdef __NR_set_robust_list case __NR_set_robust_list: return Allow(); #endif #ifdef ANDROID case __NR_set_tid_address: return Allow(); #endif // prctl case __NR_prctl: return PrctlPolicy(); // NSPR can call this when creating a thread, but it will accept a // polite "no". case __NR_getpriority: // But if thread creation races with sandbox startup, that call // could succeed, and then we get one of these: case __NR_setpriority: return Error(EACCES); // Stack bounds are obtained via pthread_getattr_np, which calls // this but doesn't actually need it: case __NR_sched_getaffinity: return Error(ENOSYS); // Read own pid/tid. case __NR_getpid: case __NR_gettid: return Allow(); // Discard capabilities case __NR_close: return Allow(); // Machine-dependent stuff #ifdef __arm__ case __ARM_NR_breakpoint: case __ARM_NR_cacheflush: case __ARM_NR_usr26: // FIXME: do we actually need this? case __ARM_NR_usr32: case __ARM_NR_set_tls: return Allow(); #endif // Needed when being debugged: case __NR_restart_syscall: return Allow(); // Terminate threads or the process case __NR_exit: case __NR_exit_group: return Allow(); #ifdef MOZ_ASAN // ASAN's error reporter wants to know if stderr is a tty. case __NR_ioctl: { Arg<int> fd(0); return If(fd == STDERR_FILENO, Allow()) .Else(InvalidSyscall()); } // ...and before compiler-rt r209773, it will call readlink on // /proc/self/exe and use the cached value only if that fails: case __NR_readlink: case __NR_readlinkat: return Error(ENOENT); // ...and if it found an external symbolizer, it will try to run it: // (See also bug 1081242 comment #7.) CASES_FOR_stat: return Error(ENOENT); #endif default: return SandboxPolicyBase::EvaluateSyscall(sysno); } }
// SecureNAT server-side thread void SnSecureNATThread(THREAD *t, void *param) { SNAT *s; CONNECTION *c; SESSION *se; POLICY *policy; HUB *h; // Validate arguments if (t == NULL || param == NULL) { return; } s = (SNAT *)param; // Create a server connection c = NewServerConnection(s->Cedar, NULL, t); c->Protocol = CONNECTION_HUB_SECURE_NAT; // Apply the default policy policy = ClonePolicy(GetDefaultPolicy()); // Not to limit the number of broadcast policy->NoBroadcastLimiter = true; h = s->Hub; AddRef(h->ref); // create a server session se = NewServerSession(s->Cedar, c, s->Hub, SNAT_USER_NAME, policy); se->SecureNATMode = true; se->SecureNAT = s; c->Session = se; ReleaseConnection(c); HLog(se->Hub, "LH_NAT_START", se->Name); // User name se->Username = CopyStr(SNAT_USER_NAME_PRINT); s->Session = se; AddRef(se->ref); // Notification initialization completion NoticeThreadInit(t); ReleaseCancel(s->Nat->Virtual->Cancel); s->Nat->Virtual->Cancel = se->Cancel1; AddRef(se->Cancel1->ref); if (s->Nat->Virtual->NativeNat != NULL) { CANCEL *old_cancel = NULL; Lock(s->Nat->Virtual->NativeNat->CancelLock); { if (s->Nat->Virtual->NativeNat->Cancel != NULL) { old_cancel = s->Nat->Virtual->NativeNat->Cancel; s->Nat->Virtual->NativeNat->Cancel = se->Cancel1; AddRef(se->Cancel1->ref); } } Unlock(s->Nat->Virtual->NativeNat->CancelLock); if (old_cancel != NULL) { ReleaseCancel(old_cancel); } } // Main function of the session Debug("SecureNAT Start.\n"); SessionMain(se); Debug("SecureNAT Stop.\n"); HLog(se->Hub, "LH_NAT_STOP"); ReleaseHub(h); ReleaseSession(se); }