Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

powerpc/rtas: Move token validation from block_rtas_call() to sys_rtas()

The rtas system call handler sys_rtas() delegates certain input
validation steps to a helper function: block_rtas_call(). One of these
steps ensures that the user-supplied token value maps to a known RTAS
function. This is done by performing a "reverse" token-to-function
lookup via rtas_token_to_function_untrusted() to obtain an
rtas_function object.

In changes to come, sys_rtas() itself will need the function
descriptor for the token. To prepare:

* Move the lookup and validation up into sys_rtas() and pass the
resulting rtas_function pointer to block_rtas_call(), which is
otherwise unconcerned with the token value.

* Change block_rtas_call() to report the RTAS function name instead of
the token value on validation failures, since it can now rely on
having a valid function descriptor.

One behavior change is that sys_rtas() now silently errors out when
passed a bad token, before calling block_rtas_call(). So we will no
longer log "RTAS call blocked - exploit attempt?" on invalid
tokens. This is consistent with how sys_rtas() currently handles other
"metadata" (nargs and nret), while block_rtas_call() is primarily
concerned with validating the arguments to be passed to specific RTAS
functions.

Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20231212-papr-sys_rtas-vs-lockdown-v6-5-e9eafd0c8c6c@linux.ibm.com

authored by

Nathan Lynch and committed by
Michael Ellerman
e7582edb 9592aa5a

+16 -16
+16 -16
arch/powerpc/kernel/rtas.c
··· 1738 1738 end < (rtas_rmo_buf + RTAS_USER_REGION_SIZE); 1739 1739 } 1740 1740 1741 - static bool block_rtas_call(int token, int nargs, 1741 + static bool block_rtas_call(const struct rtas_function *func, int nargs, 1742 1742 struct rtas_args *args) 1743 1743 { 1744 - const struct rtas_function *func; 1745 1744 const struct rtas_filter *f; 1746 - const bool is_platform_dump = token == rtas_function_token(RTAS_FN_IBM_PLATFORM_DUMP); 1747 - const bool is_config_conn = token == rtas_function_token(RTAS_FN_IBM_CONFIGURE_CONNECTOR); 1745 + const bool is_platform_dump = 1746 + func == &rtas_function_table[RTAS_FNIDX__IBM_PLATFORM_DUMP]; 1747 + const bool is_config_conn = 1748 + func == &rtas_function_table[RTAS_FNIDX__IBM_CONFIGURE_CONNECTOR]; 1748 1749 u32 base, size, end; 1749 1750 1750 1751 /* 1751 - * If this token doesn't correspond to a function the kernel 1752 - * understands, you're not allowed to call it. 1753 - */ 1754 - func = rtas_token_to_function_untrusted(token); 1755 - if (!func) 1756 - goto err; 1757 - /* 1758 - * And only functions with filters attached are allowed. 1752 + * Only functions with filters attached are allowed. 1759 1753 */ 1760 1754 f = func->filter; 1761 1755 if (!f) ··· 1806 1812 return false; 1807 1813 err: 1808 1814 pr_err_ratelimited("sys_rtas: RTAS call blocked - exploit attempt?\n"); 1809 - pr_err_ratelimited("sys_rtas: token=0x%x, nargs=%d (called by %s)\n", 1810 - token, nargs, current->comm); 1815 + pr_err_ratelimited("sys_rtas: %s nargs=%d (called by %s)\n", 1816 + func->name, nargs, current->comm); 1811 1817 return true; 1812 1818 } 1813 1819 1814 1820 /* We assume to be passed big endian arguments */ 1815 1821 SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs) 1816 1822 { 1823 + const struct rtas_function *func; 1817 1824 struct pin_cookie cookie; 1818 1825 struct rtas_args args; 1819 1826 unsigned long flags; ··· 1844 1849 nargs * sizeof(rtas_arg_t)) != 0) 1845 1850 return -EFAULT; 1846 1851 1847 - if (token == RTAS_UNKNOWN_SERVICE) 1852 + /* 1853 + * If this token doesn't correspond to a function the kernel 1854 + * understands, you're not allowed to call it. 1855 + */ 1856 + func = rtas_token_to_function_untrusted(token); 1857 + if (!func) 1848 1858 return -EINVAL; 1849 1859 1850 1860 args.rets = &args.args[nargs]; 1851 1861 memset(args.rets, 0, nret * sizeof(rtas_arg_t)); 1852 1862 1853 - if (block_rtas_call(token, nargs, &args)) 1863 + if (block_rtas_call(func, nargs, &args)) 1854 1864 return -EINVAL; 1855 1865 1856 1866 if (token_is_restricted_errinjct(token)) {