int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid, const time_t shm_createtime) { #ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT struct pid *pid = NULL; time_t starttime; if (unlikely(!grsec_enable_chroot_shmat)) return 1; if (likely(!proc_is_chrooted(current))) return 1; read_lock(&tasklist_lock); pid = find_vpid(shm_cprid); if (pid) { struct task_struct *p; p = pid_task(pid, PIDTYPE_PID); task_lock(p); starttime = p->start_time.tv_sec; if (unlikely(!have_same_root(current, p) && time_before_eq((unsigned long)starttime, (unsigned long)shm_createtime))) { task_unlock(p); read_unlock(&tasklist_lock); gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG); return 0; } task_unlock(p); } else { pid = find_vpid(shm_lapid); if (pid) { struct task_struct *p; p = pid_task(pid, PIDTYPE_PID); task_lock(p); if (unlikely(!have_same_root(current, p))) { task_unlock(p); read_unlock(&tasklist_lock); gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG); return 0; } task_unlock(p); } } read_unlock(&tasklist_lock); #endif return 1; }
int gr_handle_chroot_unix(const pid_t pid) { #ifdef CONFIG_GRKERNSEC_CHROOT_UNIX struct pid *spid = NULL; if (unlikely(!grsec_enable_chroot_unix)) return 1; if (likely(!proc_is_chrooted(current))) return 1; read_lock(&tasklist_lock); spid = find_vpid(pid); if (spid) { struct task_struct *p; p = pid_task(spid, PIDTYPE_PID); task_lock(p); if (unlikely(!have_same_root(current, p))) { task_unlock(p); read_unlock(&tasklist_lock); gr_log_noargs(GR_DONT_AUDIT, GR_UNIX_CHROOT_MSG); return 0; } task_unlock(p); } read_unlock(&tasklist_lock); #endif return 1; }
int gr_handle_chroot_unix(const pid_t pid) { #ifdef CONFIG_GRKERNSEC_CHROOT_UNIX struct task_struct *p; if (unlikely(!grsec_enable_chroot_unix)) return 1; if (likely(!proc_is_chrooted(current))) return 1; rcu_read_lock(); read_lock(&tasklist_lock); p = find_task_by_vpid_unrestricted(pid); if (unlikely(p && !have_same_root(current, p))) { read_unlock(&tasklist_lock); rcu_read_unlock(); gr_log_noargs(GR_DONT_AUDIT, GR_UNIX_CHROOT_MSG); return 0; } read_unlock(&tasklist_lock); rcu_read_unlock(); #endif return 1; }
int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid, const time_t shm_createtime) { #ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT struct task_struct *p; time_t starttime; if (unlikely(!grsec_enable_chroot_shmat)) return 1; if (likely(!proc_is_chrooted(current))) return 1; rcu_read_lock(); read_lock(&tasklist_lock); if ((p = find_task_by_vpid_unrestricted(shm_cprid))) { starttime = p->start_time.tv_sec; if (time_before_eq((unsigned long)starttime, (unsigned long)shm_createtime)) { if (have_same_root(current, p)) { goto allow; } else { read_unlock(&tasklist_lock); rcu_read_unlock(); gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG); return 0; } } /* creator exited, pid reuse, fall through to next check */ } if ((p = find_task_by_vpid_unrestricted(shm_lapid))) { if (unlikely(!have_same_root(current, p))) { read_unlock(&tasklist_lock); rcu_read_unlock(); gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG); return 0; } } allow: read_unlock(&tasklist_lock); rcu_read_unlock(); #endif return 1; }
int gr_pid_is_chrooted(struct task_struct *p) { #ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || p == NULL) return 0; if ((p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) || !have_same_root(current, p)) { return 1; } #endif return 0; }
int gr_handle_chroot_fowner(struct pid *pid, enum pid_type type) { #ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK struct task_struct *p; int ret = 0; if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || !pid) return ret; read_lock(&tasklist_lock); do_each_pid_task(pid, type, p) { if (!have_same_root(current, p)) { ret = 1; goto out; } } while_each_pid_task(pid, type, p); out: read_unlock(&tasklist_lock); return ret; #endif return 0; }
/* * Give path as relative to prefix. * * The strbuf may or may not be used, so do not assume it contains the * returned path. */ const char *relative_path(const char *in, const char *prefix, struct strbuf *sb) { int in_len = in ? strlen(in) : 0; int prefix_len = prefix ? strlen(prefix) : 0; int in_off = 0; int prefix_off = 0; int i = 0, j = 0; if (!in_len) return "./"; else if (!prefix_len) return in; if (have_same_root(in, prefix)) /* bypass dos_drive, for "c:" is identical to "C:" */ i = j = has_dos_drive_prefix(in); else { return in; } while (i < prefix_len && j < in_len && prefix[i] == in[j]) { if (is_dir_sep(prefix[i])) { while (is_dir_sep(prefix[i])) i++; while (is_dir_sep(in[j])) j++; prefix_off = i; in_off = j; } else { i++; j++; } } if ( /* "prefix" seems like prefix of "in" */ i >= prefix_len && /* * but "/foo" is not a prefix of "/foobar" * (i.e. prefix not end with '/') */ prefix_off < prefix_len) { if (j >= in_len) { /* in="/a/b", prefix="/a/b" */ in_off = in_len; } else if (is_dir_sep(in[j])) { /* in="/a/b/c", prefix="/a/b" */ while (is_dir_sep(in[j])) j++; in_off = j; } else { /* in="/a/bbb/c", prefix="/a/b" */ i = prefix_off; } } else if ( /* "in" is short than "prefix" */ j >= in_len && /* "in" not end with '/' */ in_off < in_len) { if (is_dir_sep(prefix[i])) { /* in="/a/b", prefix="/a/b/c/" */ while (is_dir_sep(prefix[i])) i++; in_off = in_len; } } in += in_off; in_len -= in_off; if (i >= prefix_len) { if (!in_len) return "./"; else return in; } strbuf_reset(sb); strbuf_grow(sb, in_len); while (i < prefix_len) { if (is_dir_sep(prefix[i])) { strbuf_addstr(sb, "../"); while (is_dir_sep(prefix[i])) i++; continue; } i++; } if (!is_dir_sep(prefix[prefix_len - 1])) strbuf_addstr(sb, "../"); strbuf_addstr(sb, in); return sb->buf; }