forked from mirrors/linux
		
	bpf: Added new helper bpf_get_ns_current_pid_tgid
New bpf helper bpf_get_ns_current_pid_tgid, This helper will return pid and tgid from current task which namespace matches dev_t and inode number provided, this will allows us to instrument a process inside a container. Signed-off-by: Carlos Neira <cneirabustos@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20200304204157.58695-3-cneirabustos@gmail.com
This commit is contained in:
		
							parent
							
								
									1e2328e762
								
							
						
					
					
						commit
						b4490c5c4e
					
				
					 7 changed files with 88 additions and 2 deletions
				
			
		|  | @ -1497,6 +1497,7 @@ extern const struct bpf_func_proto bpf_strtol_proto; | |||
| extern const struct bpf_func_proto bpf_strtoul_proto; | ||||
| extern const struct bpf_func_proto bpf_tcp_sock_proto; | ||||
| extern const struct bpf_func_proto bpf_jiffies64_proto; | ||||
| extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto; | ||||
| 
 | ||||
| /* Shared helpers among cBPF and eBPF. */ | ||||
| void bpf_user_rnd_init_once(void); | ||||
|  |  | |||
|  | @ -2914,6 +2914,19 @@ union bpf_attr { | |||
|  *		of sizeof(struct perf_branch_entry). | ||||
|  * | ||||
|  *		**-ENOENT** if architecture does not support branch records. | ||||
|  * | ||||
|  * int bpf_get_ns_current_pid_tgid(u64 dev, u64 ino, struct bpf_pidns_info *nsdata, u32 size) | ||||
|  *	Description | ||||
|  *		Returns 0 on success, values for *pid* and *tgid* as seen from the current | ||||
|  *		*namespace* will be returned in *nsdata*. | ||||
|  * | ||||
|  *		On failure, the returned value is one of the following: | ||||
|  * | ||||
|  *		**-EINVAL** if dev and inum supplied don't match dev_t and inode number | ||||
|  *              with nsfs of current task, or if dev conversion to dev_t lost high bits. | ||||
|  * | ||||
|  *		**-ENOENT** if pidns does not exists for the current task. | ||||
|  * | ||||
|  */ | ||||
| #define __BPF_FUNC_MAPPER(FN)		\ | ||||
| 	FN(unspec),			\ | ||||
|  | @ -3035,7 +3048,8 @@ union bpf_attr { | |||
| 	FN(tcp_send_ack),		\ | ||||
| 	FN(send_signal_thread),		\ | ||||
| 	FN(jiffies64),			\ | ||||
| 	FN(read_branch_records), | ||||
| 	FN(read_branch_records),	\ | ||||
| 	FN(get_ns_current_pid_tgid), | ||||
| 
 | ||||
| /* integer value in 'imm' field of BPF_CALL instruction selects which helper
 | ||||
|  * function eBPF program intends to call | ||||
|  | @ -3829,4 +3843,8 @@ struct bpf_sockopt { | |||
| 	__s32	retval; | ||||
| }; | ||||
| 
 | ||||
| struct bpf_pidns_info { | ||||
| 	__u32 pid; | ||||
| 	__u32 tgid; | ||||
| }; | ||||
| #endif /* _UAPI__LINUX_BPF_H__ */ | ||||
|  |  | |||
|  | @ -2149,6 +2149,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak; | |||
| const struct bpf_func_proto bpf_get_current_comm_proto __weak; | ||||
| const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak; | ||||
| const struct bpf_func_proto bpf_get_local_storage_proto __weak; | ||||
| const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto __weak; | ||||
| 
 | ||||
| const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void) | ||||
| { | ||||
|  |  | |||
|  | @ -12,6 +12,8 @@ | |||
| #include <linux/filter.h> | ||||
| #include <linux/ctype.h> | ||||
| #include <linux/jiffies.h> | ||||
| #include <linux/pid_namespace.h> | ||||
| #include <linux/proc_ns.h> | ||||
| 
 | ||||
| #include "../../lib/kstrtox.h" | ||||
| 
 | ||||
|  | @ -499,3 +501,46 @@ const struct bpf_func_proto bpf_strtoul_proto = { | |||
| 	.arg4_type	= ARG_PTR_TO_LONG, | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| BPF_CALL_4(bpf_get_ns_current_pid_tgid, u64, dev, u64, ino, | ||||
| 	   struct bpf_pidns_info *, nsdata, u32, size) | ||||
| { | ||||
| 	struct task_struct *task = current; | ||||
| 	struct pid_namespace *pidns; | ||||
| 	int err = -EINVAL; | ||||
| 
 | ||||
| 	if (unlikely(size != sizeof(struct bpf_pidns_info))) | ||||
| 		goto clear; | ||||
| 
 | ||||
| 	if (unlikely((u64)(dev_t)dev != dev)) | ||||
| 		goto clear; | ||||
| 
 | ||||
| 	if (unlikely(!task)) | ||||
| 		goto clear; | ||||
| 
 | ||||
| 	pidns = task_active_pid_ns(task); | ||||
| 	if (unlikely(!pidns)) { | ||||
| 		err = -ENOENT; | ||||
| 		goto clear; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!ns_match(&pidns->ns, (dev_t)dev, ino)) | ||||
| 		goto clear; | ||||
| 
 | ||||
| 	nsdata->pid = task_pid_nr_ns(task, pidns); | ||||
| 	nsdata->tgid = task_tgid_nr_ns(task, pidns); | ||||
| 	return 0; | ||||
| clear: | ||||
| 	memset((void *)nsdata, 0, (size_t) size); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto = { | ||||
| 	.func		= bpf_get_ns_current_pid_tgid, | ||||
| 	.gpl_only	= false, | ||||
| 	.ret_type	= RET_INTEGER, | ||||
| 	.arg1_type	= ARG_ANYTHING, | ||||
| 	.arg2_type	= ARG_ANYTHING, | ||||
| 	.arg3_type      = ARG_PTR_TO_UNINIT_MEM, | ||||
| 	.arg4_type      = ARG_CONST_SIZE, | ||||
| }; | ||||
|  |  | |||
|  | @ -843,6 +843,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | |||
| 		return &bpf_send_signal_thread_proto; | ||||
| 	case BPF_FUNC_perf_event_read_value: | ||||
| 		return &bpf_perf_event_read_value_proto; | ||||
| 	case BPF_FUNC_get_ns_current_pid_tgid: | ||||
| 		return &bpf_get_ns_current_pid_tgid_proto; | ||||
| 	default: | ||||
| 		return NULL; | ||||
| 	} | ||||
|  |  | |||
|  | @ -435,6 +435,7 @@ class PrinterHelpers(Printer): | |||
|             'struct bpf_fib_lookup', | ||||
|             'struct bpf_perf_event_data', | ||||
|             'struct bpf_perf_event_value', | ||||
|             'struct bpf_pidns_info', | ||||
|             'struct bpf_sock', | ||||
|             'struct bpf_sock_addr', | ||||
|             'struct bpf_sock_ops', | ||||
|  |  | |||
|  | @ -2914,6 +2914,19 @@ union bpf_attr { | |||
|  *		of sizeof(struct perf_branch_entry). | ||||
|  * | ||||
|  *		**-ENOENT** if architecture does not support branch records. | ||||
|  * | ||||
|  * int bpf_get_ns_current_pid_tgid(u64 dev, u64 ino, struct bpf_pidns_info *nsdata, u32 size) | ||||
|  *	Description | ||||
|  *		Returns 0 on success, values for *pid* and *tgid* as seen from the current | ||||
|  *		*namespace* will be returned in *nsdata*. | ||||
|  * | ||||
|  *		On failure, the returned value is one of the following: | ||||
|  * | ||||
|  *		**-EINVAL** if dev and inum supplied don't match dev_t and inode number | ||||
|  *              with nsfs of current task, or if dev conversion to dev_t lost high bits. | ||||
|  * | ||||
|  *		**-ENOENT** if pidns does not exists for the current task. | ||||
|  * | ||||
|  */ | ||||
| #define __BPF_FUNC_MAPPER(FN)		\ | ||||
| 	FN(unspec),			\ | ||||
|  | @ -3035,7 +3048,8 @@ union bpf_attr { | |||
| 	FN(tcp_send_ack),		\ | ||||
| 	FN(send_signal_thread),		\ | ||||
| 	FN(jiffies64),			\ | ||||
| 	FN(read_branch_records), | ||||
| 	FN(read_branch_records),	\ | ||||
| 	FN(get_ns_current_pid_tgid), | ||||
| 
 | ||||
| /* integer value in 'imm' field of BPF_CALL instruction selects which helper
 | ||||
|  * function eBPF program intends to call | ||||
|  | @ -3829,4 +3843,8 @@ struct bpf_sockopt { | |||
| 	__s32	retval; | ||||
| }; | ||||
| 
 | ||||
| struct bpf_pidns_info { | ||||
| 	__u32 pid; | ||||
| 	__u32 tgid; | ||||
| }; | ||||
| #endif /* _UAPI__LINUX_BPF_H__ */ | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Carlos Neira
						Carlos Neira