(root)/
strace-6.5/
src/
kd_mpers_ioctl.c
       1  /*
       2   * Support for decoding of personality-dependent VT ioctl commands.
       3   *
       4   * Copyright (c) 2019-2021 Eugene Syromyatnikov <evgsyr@gmail.com>
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   */
       9  
      10  #include "defs.h"
      11  
      12  #include <linux/kd.h>
      13  
      14  #include DEF_MPERS_TYPE(struct_unimapdesc)
      15  #include DEF_MPERS_TYPE(struct_consolefontdesc)
      16  #include DEF_MPERS_TYPE(struct_console_font)
      17  #include DEF_MPERS_TYPE(struct_console_font_op)
      18  
      19  typedef struct unimapdesc struct_unimapdesc;
      20  typedef struct consolefontdesc struct_consolefontdesc;
      21  typedef struct console_font struct_console_font;
      22  typedef struct console_font_op struct_console_font_op;
      23  
      24  #include MPERS_DEFS
      25  
      26  #include "print_fields.h"
      27  
      28  #include "xlat/kd_font_flags.h"
      29  #include "xlat/kd_font_ops.h"
      30  
      31  #define XLAT_MACROS_ONLY
      32  # include "xlat/kd_ioctl_cmds.h"
      33  #undef XLAT_MACROS_ONLY
      34  
      35  
      36  static bool
      37  print_unipair_array_member(struct tcb *tcp, void *elem_buf,
      38  			   size_t elem_size, void *data)
      39  {
      40  	struct unipair *val = elem_buf;
      41  
      42  	tprint_struct_begin();
      43  	PRINT_FIELD_X(*val, unicode);
      44  	tprint_struct_next();
      45  	PRINT_FIELD_X(*val, fontpos);
      46  	tprint_struct_end();
      47  
      48  	return true;
      49  }
      50  
      51  static int
      52  kd_unimap(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
      53  {
      54  	struct_unimapdesc val;
      55  	struct unipair elem;
      56  	uint16_t cnt;
      57  
      58  	if (entering(tcp))
      59  		tprint_arg_next();
      60  
      61  	if (umove_or_printaddr_ignore_syserror(tcp, arg, &val)) {
      62  		if (exiting(tcp))
      63  			tprint_struct_end();
      64  
      65  		return RVAL_IOCTL_DECODED;
      66  	}
      67  
      68  	if (entering(tcp)) {
      69  		set_tcb_priv_ulong(tcp, val.entry_ct);
      70  		tprint_struct_begin();
      71  		PRINT_FIELD_U(val, entry_ct);
      72  
      73  		if (get)
      74  			return 0;
      75  	} else {
      76  		tprint_value_changed();
      77  		PRINT_VAL_U(val.entry_ct);
      78  	}
      79  
      80  	if (exiting(tcp) && syserror(tcp) && tcp->u_error != ENOMEM) {
      81  		tprint_struct_next();
      82  		PRINT_FIELD_PTR(val, entries);
      83  		tprint_struct_end();
      84  		return RVAL_IOCTL_DECODED;
      85  	}
      86  
      87  	cnt = entering(tcp) ? val.entry_ct : get_tcb_priv_ulong(tcp);
      88  
      89  	tprint_struct_next();
      90  	tprints_field_name("entries");
      91  	print_array(tcp, (mpers_ptr_t) val.entries, cnt, &elem, sizeof(elem),
      92  		    tfetch_mem, print_unipair_array_member, 0);
      93  
      94  	tprint_struct_end();
      95  
      96  	return get && entering(tcp) ? 0 : RVAL_IOCTL_DECODED;
      97  }
      98  
      99  static void
     100  print_consolefontdesc(struct tcb *const tcp, const struct_consolefontdesc *cfd,
     101  		      const bool get)
     102  {
     103  	tprint_struct_begin();
     104  	PRINT_FIELD_U(*cfd, charcount);
     105  	tprint_struct_next();
     106  	PRINT_FIELD_U(*cfd, charheight);
     107  	tprint_struct_next();
     108  	if (get) {
     109  		PRINT_FIELD_PTR(*cfd, chardata);
     110  	} else {
     111  		tprints_field_name("chardata");
     112  		printstr_ex(tcp, (mpers_ptr_t) cfd->chardata,
     113  			    MIN(cfd->charcount, 512) * 32, QUOTE_FORCE_HEX);
     114  	}
     115  
     116  	tprint_struct_end();
     117  }
     118  
     119  static int
     120  kd_fontx(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     121  {
     122  	struct_consolefontdesc val;
     123  
     124  	if (entering(tcp)) {
     125  		tprint_arg_next();
     126  
     127  		if (umove_or_printaddr(tcp, arg, &val))
     128  			return RVAL_IOCTL_DECODED;
     129  	} else {
     130  		if (syserror(tcp) || umove(tcp, arg, &val))
     131  			return RVAL_IOCTL_DECODED;
     132  
     133  		tprint_value_changed();
     134  	}
     135  
     136  	print_consolefontdesc(tcp, &val, get && entering(tcp));
     137  
     138  	return get && entering(tcp) ? 0 : RVAL_IOCTL_DECODED;
     139  }
     140  
     141  static void
     142  print_console_font_op(struct tcb *const tcp, const struct_console_font_op *cfo)
     143  {
     144  	enum { KERNEL_MAX_FONT_NAME = 32 };
     145  
     146  	tprint_struct_begin();
     147  
     148  	if (entering(tcp)) {
     149  		PRINT_FIELD_XVAL(*cfo, op, kd_font_ops, "KD_FONT_OP_???");
     150  
     151  		switch (cfo->op) {
     152  		case KD_FONT_OP_SET_DEFAULT:
     153  		case KD_FONT_OP_COPY:
     154  			break;
     155  		default:
     156  			tprint_struct_next();
     157  			PRINT_FIELD_FLAGS(*cfo, flags, kd_font_flags,
     158  					  "KD_FONT_FLAG_???");
     159  		}
     160  
     161  		tprint_struct_next();
     162  	}
     163  
     164  	switch (cfo->op) {
     165  	case KD_FONT_OP_COPY:
     166  		PRINT_FIELD_U(*cfo, height);
     167  		break;
     168  	default:
     169  		PRINT_FIELD_U(*cfo, width);
     170  		tprint_struct_next();
     171  		PRINT_FIELD_U(*cfo, height);
     172  	}
     173  
     174  	switch (cfo->op) {
     175  	case KD_FONT_OP_SET_DEFAULT:
     176  	case KD_FONT_OP_COPY:
     177  		break;
     178  	default:
     179  		tprint_struct_next();
     180  		PRINT_FIELD_U(*cfo, charcount);
     181  	}
     182  
     183  	switch (cfo->op) {
     184  	case KD_FONT_OP_GET:
     185  		if (entering(tcp)) {
     186  			tprint_struct_next();
     187  			PRINT_FIELD_PTR(*cfo, data);
     188  			break;
     189  		}
     190  		ATTRIBUTE_FALLTHROUGH;
     191  
     192  	case KD_FONT_OP_SET:
     193  		tprint_struct_next();
     194  		tprints_field_name("data");
     195  		printstr_ex(tcp, (mpers_ptr_t) cfo->data,
     196  			    ROUNDUP_DIV(MIN(cfo->width, 32), 8) * 32 *
     197  				MIN(cfo->charcount, 512),
     198  			    QUOTE_FORCE_HEX);
     199  		break;
     200  
     201  	case KD_FONT_OP_SET_DEFAULT:
     202  		if (entering(tcp)) {
     203  			tprint_struct_next();
     204  			tprints_field_name("data");
     205  			printstr_ex(tcp, (mpers_ptr_t) cfo->data,
     206  				    KERNEL_MAX_FONT_NAME,
     207  				    QUOTE_0_TERMINATED
     208  				    | QUOTE_EXPECT_TRAILING_0);
     209  		}
     210  		break;
     211  
     212  	case KD_FONT_OP_COPY:
     213  		break;
     214  
     215  	default:
     216  		tprint_struct_next();
     217  		PRINT_FIELD_PTR(*cfo, data);
     218  	}
     219  
     220  	tprint_struct_end();
     221  }
     222  
     223  static int
     224  kd_font_op(struct tcb *const tcp, const kernel_ulong_t arg)
     225  {
     226  	struct_console_font_op val;
     227  
     228  	if (entering(tcp)) {
     229  		tprint_arg_next();
     230  
     231  		if (umove_or_printaddr(tcp, arg, &val))
     232  			return RVAL_IOCTL_DECODED;
     233  	} else {
     234  		if (syserror(tcp) || umove(tcp, arg, &val))
     235  			return RVAL_IOCTL_DECODED;
     236  
     237  		tprint_value_changed();
     238  	}
     239  
     240  	print_console_font_op(tcp, &val);
     241  
     242  	switch (val.op) {
     243  	case KD_FONT_OP_SET:
     244  	case KD_FONT_OP_COPY:
     245  		return RVAL_IOCTL_DECODED;
     246  	}
     247  
     248  	return entering(tcp) ? 0 : RVAL_IOCTL_DECODED;
     249  }
     250  
     251  MPERS_PRINTER_DECL(int, kd_mpers_ioctl, struct tcb *const tcp,
     252  		   const unsigned int code, const kernel_ulong_t arg)
     253  {
     254  	switch (code)
     255  	{
     256  	case GIO_UNIMAP:
     257  	case PIO_UNIMAP:
     258  		return kd_unimap(tcp, arg, code == GIO_UNIMAP);
     259  
     260  	case GIO_FONTX:
     261  	case PIO_FONTX:
     262  		return kd_fontx(tcp, arg, code == GIO_FONTX);
     263  
     264  	case KDFONTOP:
     265  		return kd_font_op(tcp, arg);
     266  	}
     267  
     268  	return RVAL_DECODED;
     269  }