mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	seccomp: recheck the syscall after RET_TRACE
When RET_TRACE triggers, a tracer may change a syscall into something that should be filtered by seccomp. This re-runs seccomp after a trace event to make sure things continue to pass. Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Andy Lutomirski <luto@kernel.org>
This commit is contained in:
		
							parent
							
								
									8112c4f140
								
							
						
					
					
						commit
						ce6526e8af
					
				
					 1 changed files with 18 additions and 3 deletions
				
			
		| 
						 | 
					@ -556,7 +556,8 @@ void secure_computing_strict(int this_syscall)
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SECCOMP_FILTER
 | 
					#ifdef CONFIG_SECCOMP_FILTER
 | 
				
			||||||
static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
 | 
					static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 | 
				
			||||||
 | 
								    const bool recheck_after_trace)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 filter_ret, action;
 | 
						u32 filter_ret, action;
 | 
				
			||||||
	int data;
 | 
						int data;
 | 
				
			||||||
| 
						 | 
					@ -588,6 +589,10 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
 | 
				
			||||||
		goto skip;
 | 
							goto skip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SECCOMP_RET_TRACE:
 | 
						case SECCOMP_RET_TRACE:
 | 
				
			||||||
 | 
							/* We've been put in this state by the ptracer already. */
 | 
				
			||||||
 | 
							if (recheck_after_trace)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* ENOSYS these calls if there is no tracer attached. */
 | 
							/* ENOSYS these calls if there is no tracer attached. */
 | 
				
			||||||
		if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
 | 
							if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
 | 
				
			||||||
			syscall_set_return_value(current,
 | 
								syscall_set_return_value(current,
 | 
				
			||||||
| 
						 | 
					@ -611,6 +616,15 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
 | 
				
			||||||
		if (this_syscall < 0)
 | 
							if (this_syscall < 0)
 | 
				
			||||||
			goto skip;
 | 
								goto skip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Recheck the syscall, since it may have changed. This
 | 
				
			||||||
 | 
							 * intentionally uses a NULL struct seccomp_data to force
 | 
				
			||||||
 | 
							 * a reload of all registers. This does not goto skip since
 | 
				
			||||||
 | 
							 * a skip would have already been reported.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (__seccomp_filter(this_syscall, NULL, true))
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SECCOMP_RET_ALLOW:
 | 
						case SECCOMP_RET_ALLOW:
 | 
				
			||||||
| 
						 | 
					@ -629,7 +643,8 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
 | 
				
			||||||
	return -1;
 | 
						return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
 | 
					static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 | 
				
			||||||
 | 
								    const bool recheck_after_trace)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	BUG();
 | 
						BUG();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -652,7 +667,7 @@ int __secure_computing(const struct seccomp_data *sd)
 | 
				
			||||||
		__secure_computing_strict(this_syscall);  /* may call do_exit */
 | 
							__secure_computing_strict(this_syscall);  /* may call do_exit */
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	case SECCOMP_MODE_FILTER:
 | 
						case SECCOMP_MODE_FILTER:
 | 
				
			||||||
		return __seccomp_filter(this_syscall, sd);
 | 
							return __seccomp_filter(this_syscall, sd, false);
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		BUG();
 | 
							BUG();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue