diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2024-06-02 14:25:46 -0400 | 
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2024-11-03 01:28:06 -0500 | 
| commit | 4dd53b84ff23424e2fe1e902decacdb49303e3d3 (patch) | |
| tree | 347e4a10859fa55d60f3442f55a6503cbbab7d12 /kernel/events | |
| parent | 919a7a1aac29f7f1ec945dccdf084d494991c78c (diff) | |
get rid of perf_fget_light(), convert kernel/events/core.c to CLASS(fd)
Lift fdget() and fdput() out of perf_fget_light(), turning it into
is_perf_file(struct fd f).  The life gets easier in both callers
if we do fdget() unconditionally, including the case when we are
given -1 instead of a descriptor - that avoids a reassignment in
perf_event_open(2) and it avoids a nasty temptation in _perf_ioctl()
where we must *not* lift output_event out of scope for output.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/events')
| -rw-r--r-- | kernel/events/core.c | 49 | 
1 files changed, 16 insertions, 33 deletions
| diff --git a/kernel/events/core.c b/kernel/events/core.c index e3589c4287cb..85b209626dd7 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5998,18 +5998,9 @@ EXPORT_SYMBOL_GPL(perf_event_period);  static const struct file_operations perf_fops; -static inline int perf_fget_light(int fd, struct fd *p) +static inline bool is_perf_file(struct fd f)  { -	struct fd f = fdget(fd); -	if (!fd_file(f)) -		return -EBADF; - -	if (fd_file(f)->f_op != &perf_fops) { -		fdput(f); -		return -EBADF; -	} -	*p = f; -	return 0; +	return !fd_empty(f) && fd_file(f)->f_op == &perf_fops;  }  static int perf_event_set_output(struct perf_event *event, @@ -6057,20 +6048,14 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon  	case PERF_EVENT_IOC_SET_OUTPUT:  	{ -		int ret; +		CLASS(fd, output)(arg);	     // arg == -1 => empty +		struct perf_event *output_event = NULL;  		if (arg != -1) { -			struct perf_event *output_event; -			struct fd output; -			ret = perf_fget_light(arg, &output); -			if (ret) -				return ret; +			if (!is_perf_file(output)) +				return -EBADF;  			output_event = fd_file(output)->private_data; -			ret = perf_event_set_output(event, output_event); -			fdput(output); -		} else { -			ret = perf_event_set_output(event, NULL);  		} -		return ret; +		return perf_event_set_output(event, output_event);  	}  	case PERF_EVENT_IOC_SET_FILTER: @@ -12664,7 +12649,6 @@ SYSCALL_DEFINE5(perf_event_open,  	struct perf_event_attr attr;  	struct perf_event_context *ctx;  	struct file *event_file = NULL; -	struct fd group = EMPTY_FD;  	struct task_struct *task = NULL;  	struct pmu *pmu;  	int event_fd; @@ -12735,10 +12719,12 @@ SYSCALL_DEFINE5(perf_event_open,  	if (event_fd < 0)  		return event_fd; +	CLASS(fd, group)(group_fd);     // group_fd == -1 => empty  	if (group_fd != -1) { -		err = perf_fget_light(group_fd, &group); -		if (err) +		if (!is_perf_file(group)) { +			err = -EBADF;  			goto err_fd; +		}  		group_leader = fd_file(group)->private_data;  		if (flags & PERF_FLAG_FD_OUTPUT)  			output_event = group_leader; @@ -12750,7 +12736,7 @@ SYSCALL_DEFINE5(perf_event_open,  		task = find_lively_task_by_vpid(pid);  		if (IS_ERR(task)) {  			err = PTR_ERR(task); -			goto err_group_fd; +			goto err_fd;  		}  	} @@ -13017,12 +13003,11 @@ SYSCALL_DEFINE5(perf_event_open,  	mutex_unlock(¤t->perf_event_mutex);  	/* -	 * Drop the reference on the group_event after placing the -	 * new event on the sibling_list. This ensures destruction -	 * of the group leader will find the pointer to itself in -	 * perf_group_detach(). +	 * File reference in group guarantees that group_leader has been +	 * kept alive until we place the new event on the sibling_list. +	 * This ensures destruction of the group leader will find +	 * the pointer to itself in perf_group_detach().  	 */ -	fdput(group);  	fd_install(event_fd, event_file);  	return event_fd; @@ -13041,8 +13026,6 @@ err_alloc:  err_task:  	if (task)  		put_task_struct(task); -err_group_fd: -	fdput(group);  err_fd:  	put_unused_fd(event_fd);  	return err; | 
