cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cmdline.c (4775B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *
      4 * Misc librarized functions for cmdline poking.
      5 */
      6#include <linux/kernel.h>
      7#include <linux/string.h>
      8#include <linux/ctype.h>
      9#include <asm/setup.h>
     10
     11static inline int myisspace(u8 c)
     12{
     13	return c <= ' ';	/* Close enough approximation */
     14}
     15
     16/**
     17 * Find a boolean option (like quiet,noapic,nosmp....)
     18 *
     19 * @cmdline: the cmdline string
     20 * @option: option string to look for
     21 *
     22 * Returns the position of that @option (starts counting with 1)
     23 * or 0 on not found.  @option will only be found if it is found
     24 * as an entire word in @cmdline.  For instance, if @option="car"
     25 * then a cmdline which contains "cart" will not match.
     26 */
     27static int
     28__cmdline_find_option_bool(const char *cmdline, int max_cmdline_size,
     29			   const char *option)
     30{
     31	char c;
     32	int pos = 0, wstart = 0;
     33	const char *opptr = NULL;
     34	enum {
     35		st_wordstart = 0,	/* Start of word/after whitespace */
     36		st_wordcmp,	/* Comparing this word */
     37		st_wordskip,	/* Miscompare, skip */
     38	} state = st_wordstart;
     39
     40	if (!cmdline)
     41		return -1;      /* No command line */
     42
     43	/*
     44	 * This 'pos' check ensures we do not overrun
     45	 * a non-NULL-terminated 'cmdline'
     46	 */
     47	while (pos < max_cmdline_size) {
     48		c = *(char *)cmdline++;
     49		pos++;
     50
     51		switch (state) {
     52		case st_wordstart:
     53			if (!c)
     54				return 0;
     55			else if (myisspace(c))
     56				break;
     57
     58			state = st_wordcmp;
     59			opptr = option;
     60			wstart = pos;
     61			fallthrough;
     62
     63		case st_wordcmp:
     64			if (!*opptr) {
     65				/*
     66				 * We matched all the way to the end of the
     67				 * option we were looking for.  If the
     68				 * command-line has a space _or_ ends, then
     69				 * we matched!
     70				 */
     71				if (!c || myisspace(c))
     72					return wstart;
     73				/*
     74				 * We hit the end of the option, but _not_
     75				 * the end of a word on the cmdline.  Not
     76				 * a match.
     77				 */
     78			} else if (!c) {
     79				/*
     80				 * Hit the NULL terminator on the end of
     81				 * cmdline.
     82				 */
     83				return 0;
     84			} else if (c == *opptr++) {
     85				/*
     86				 * We are currently matching, so continue
     87				 * to the next character on the cmdline.
     88				 */
     89				break;
     90			}
     91			state = st_wordskip;
     92			fallthrough;
     93
     94		case st_wordskip:
     95			if (!c)
     96				return 0;
     97			else if (myisspace(c))
     98				state = st_wordstart;
     99			break;
    100		}
    101	}
    102
    103	return 0;	/* Buffer overrun */
    104}
    105
    106/*
    107 * Find a non-boolean option (i.e. option=argument). In accordance with
    108 * standard Linux practice, if this option is repeated, this returns the
    109 * last instance on the command line.
    110 *
    111 * @cmdline: the cmdline string
    112 * @max_cmdline_size: the maximum size of cmdline
    113 * @option: option string to look for
    114 * @buffer: memory buffer to return the option argument
    115 * @bufsize: size of the supplied memory buffer
    116 *
    117 * Returns the length of the argument (regardless of if it was
    118 * truncated to fit in the buffer), or -1 on not found.
    119 */
    120static int
    121__cmdline_find_option(const char *cmdline, int max_cmdline_size,
    122		      const char *option, char *buffer, int bufsize)
    123{
    124	char c;
    125	int pos = 0, len = -1;
    126	const char *opptr = NULL;
    127	char *bufptr = buffer;
    128	enum {
    129		st_wordstart = 0,	/* Start of word/after whitespace */
    130		st_wordcmp,	/* Comparing this word */
    131		st_wordskip,	/* Miscompare, skip */
    132		st_bufcpy,	/* Copying this to buffer */
    133	} state = st_wordstart;
    134
    135	if (!cmdline)
    136		return -1;      /* No command line */
    137
    138	/*
    139	 * This 'pos' check ensures we do not overrun
    140	 * a non-NULL-terminated 'cmdline'
    141	 */
    142	while (pos++ < max_cmdline_size) {
    143		c = *(char *)cmdline++;
    144		if (!c)
    145			break;
    146
    147		switch (state) {
    148		case st_wordstart:
    149			if (myisspace(c))
    150				break;
    151
    152			state = st_wordcmp;
    153			opptr = option;
    154			fallthrough;
    155
    156		case st_wordcmp:
    157			if ((c == '=') && !*opptr) {
    158				/*
    159				 * We matched all the way to the end of the
    160				 * option we were looking for, prepare to
    161				 * copy the argument.
    162				 */
    163				len = 0;
    164				bufptr = buffer;
    165				state = st_bufcpy;
    166				break;
    167			} else if (c == *opptr++) {
    168				/*
    169				 * We are currently matching, so continue
    170				 * to the next character on the cmdline.
    171				 */
    172				break;
    173			}
    174			state = st_wordskip;
    175			fallthrough;
    176
    177		case st_wordskip:
    178			if (myisspace(c))
    179				state = st_wordstart;
    180			break;
    181
    182		case st_bufcpy:
    183			if (myisspace(c)) {
    184				state = st_wordstart;
    185			} else {
    186				/*
    187				 * Increment len, but don't overrun the
    188				 * supplied buffer and leave room for the
    189				 * NULL terminator.
    190				 */
    191				if (++len < bufsize)
    192					*bufptr++ = c;
    193			}
    194			break;
    195		}
    196	}
    197
    198	if (bufsize)
    199		*bufptr = '\0';
    200
    201	return len;
    202}
    203
    204int cmdline_find_option_bool(const char *cmdline, const char *option)
    205{
    206	return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
    207}
    208
    209int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
    210			int bufsize)
    211{
    212	return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
    213				     buffer, bufsize);
    214}