(root)/
strace-6.5/
src/
tee.c
       1  /*
       2   * Copyright (c) 2020-2022 The strace developers.
       3   * All rights reserved.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   */
       7  
       8  #include "defs.h"
       9  #include <linux/tee.h>
      10  
      11  /* Not in UAPI.  */
      12  struct tee_ioctl_shm_register_fd_data {
      13  	int64_t fd;
      14  	uint64_t size;
      15  	uint32_t flags;
      16  	uint8_t _pad1[4];
      17  	int32_t id;
      18  	uint8_t _pad2[4];
      19  } ATTRIBUTE_ALIGNED(8);
      20  
      21  #define TEE_IOC_SHM_REGISTER_FD _IOWR(0xa4, 8, struct tee_ioctl_shm_register_fd_data)
      22  
      23  #include "xlat/tee_ioctl_gen_caps.h"
      24  #include "xlat/tee_ioctl_impl_ids.h"
      25  #include "xlat/tee_ioctl_login_types.h"
      26  #include "xlat/tee_ioctl_max_arg_size.h"
      27  #include "xlat/tee_ioctl_origins.h"
      28  #include "xlat/tee_ioctl_optee_caps.h"
      29  #include "xlat/tee_ioctl_param_attr_types.h"
      30  #include "xlat/tee_ioctl_shm_flags.h"
      31  
      32  #define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_ioctl_param) * (x))
      33  
      34  #define TEE_FETCH_BUF_DATA(buf_, arg_, params_) \
      35  	tee_fetch_buf_data(tcp, arg, &buf_, sizeof(arg_), \
      36  			   &arg_, offsetof(typeof(arg_), num_params), \
      37  			   params_)
      38  
      39  /* session id is printed as 0x%x in libteec */
      40  #define PRINT_FIELD_SESSION(where_, field_) \
      41  	PRINT_FIELD_X(where_, field_)
      42  
      43  static void
      44  tee_print_buf(struct tee_ioctl_buf_data *buf)
      45  {
      46  	tprint_struct_begin();
      47  	PRINT_FIELD_U(*buf, buf_len);
      48  	tprint_struct_next();
      49  	PRINT_FIELD_ADDR64(*buf, buf_ptr);
      50  	tprint_struct_end();
      51  }
      52  
      53  static int
      54  tee_fetch_buf_data(struct tcb *const tcp,
      55  		   const kernel_ulong_t arg,
      56  		   struct tee_ioctl_buf_data *buf,
      57  		   size_t arg_size,
      58  		   void *arg_struct,
      59  		   size_t num_params_offs,
      60  		   uint64_t *params)
      61  {
      62  	if (umove_or_printaddr(tcp, arg, buf))
      63  		return RVAL_IOCTL_DECODED;
      64  	if (buf->buf_len > TEE_MAX_ARG_SIZE || buf->buf_len < arg_size) {
      65  		tee_print_buf(buf);
      66  		return RVAL_IOCTL_DECODED;
      67  	}
      68  	if (umoven(tcp, buf->buf_ptr, arg_size, arg_struct)) {
      69  		tee_print_buf(buf);
      70  		return RVAL_IOCTL_DECODED;
      71  	}
      72  	uint32_t *num_params = (uint32_t *) (arg_struct + num_params_offs);
      73  	if (entering(tcp) &&
      74  	    (arg_size + TEE_IOCTL_PARAM_SIZE(*num_params) != buf->buf_len)) {
      75  		/*
      76  		 * We could print whatever number of params
      77  		 * is in buf_data, but the kernel would ignore
      78  		 * them anyway (and return -EINVAL) if
      79  		 * the above condition is not satisfied.
      80  		 *
      81  		 * Except for on exiting. The kernel has the right
      82  		 * to update num_params but not buf_len
      83  		 * (see tee_ioctl_supp_recv)
      84  		 */
      85  		tee_print_buf(buf);
      86  		return RVAL_IOCTL_DECODED;
      87  	}
      88  	if (*num_params) {
      89  		*params = buf->buf_ptr + arg_size;
      90  	} else {
      91  		*params = 0;
      92  	}
      93  
      94  	return 0;
      95  }
      96  
      97  static bool
      98  tee_print_param_fn(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
      99  {
     100  	struct tee_ioctl_param *param = (struct tee_ioctl_param *) elem_buf;
     101  
     102  	tprint_struct_begin();
     103  	tprints_field_name("attr");
     104  	tprint_flags_begin();
     105  	printxval(tee_ioctl_param_attr_types,
     106  		    param->attr & ~TEE_IOCTL_PARAM_ATTR_META,
     107  		    "TEE_IOCTL_PARAM_ATTR_");
     108  	if (param->attr & TEE_IOCTL_PARAM_ATTR_META) {
     109  		tprint_flags_or();
     110  		tprints_string("TEE_IOCTL_PARAM_ATTR_META");
     111  	}
     112  	tprint_flags_end();
     113  
     114  	switch (param->attr) {
     115  	case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
     116  		break;
     117  
     118  	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
     119  	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
     120  	case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
     121  		tprint_struct_next();
     122  		tprints_field_name("shm_offs");
     123  		PRINT_VAL_X(param->a);
     124  		tprint_struct_next();
     125  		tprints_field_name("size");
     126  		PRINT_VAL_X(param->b);
     127  		tprint_struct_next();
     128  		tprints_field_name("shm_id");
     129  		PRINT_VAL_U(param->c);
     130  		break;
     131  
     132  	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
     133  	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
     134  	case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
     135  	default:
     136  		tprint_struct_next();
     137  		PRINT_FIELD_X(*param, a);
     138  		tprint_struct_next();
     139  		PRINT_FIELD_X(*param, b);
     140  		tprint_struct_next();
     141  		PRINT_FIELD_X(*param, c);
     142  		break;
     143  	}
     144  	tprint_struct_end();
     145  	return true;
     146  }
     147  
     148  static void
     149  tee_print_params(struct tcb *const tcp, uint64_t params_start, unsigned num_params)
     150  {
     151  	struct tee_ioctl_param param_buffer;
     152  
     153  	tprint_struct_next();
     154  	tprints_field_name("params");
     155  	print_array(tcp, params_start, num_params, &param_buffer, sizeof(param_buffer),
     156  		    tfetch_mem, tee_print_param_fn, NULL);
     157  }
     158  
     159  static int
     160  tee_version(struct tcb *const tcp, const kernel_ulong_t arg)
     161  {
     162  	struct tee_ioctl_version_data version;
     163  
     164  	if (entering(tcp)) {
     165  		tprint_arg_next();
     166  		return 0;
     167  	}
     168  
     169  	if (umove_or_printaddr(tcp, arg, &version))
     170  		return RVAL_IOCTL_DECODED;
     171  
     172  	tprint_struct_begin();
     173  	PRINT_FIELD_XVAL(version, impl_id,
     174  			 tee_ioctl_impl_ids, "TEE_IMPL_ID_???");
     175  	tprint_struct_next();
     176  	PRINT_FIELD_FLAGS(version, gen_caps,
     177  			  tee_ioctl_gen_caps, "TEE_GEN_CAP_???");
     178  	if (version.impl_id == TEE_IMPL_ID_OPTEE) {
     179  		tprint_struct_next();
     180  		PRINT_FIELD_FLAGS(version, impl_caps,
     181  				  tee_ioctl_optee_caps, "TEE_OPTEE_CAP_???");
     182  	} else {
     183  		tprint_struct_next();
     184  		PRINT_FIELD_X(version, impl_caps);
     185  	}
     186  
     187  	tprint_struct_end();
     188  	return RVAL_IOCTL_DECODED;
     189  }
     190  
     191  static int
     192  tee_open_session(struct tcb *const tcp, const kernel_ulong_t arg)
     193  {
     194  	int rval;
     195  	struct tee_ioctl_buf_data buf_data;
     196  	struct tee_ioctl_open_session_arg open_session;
     197  	uint64_t params;
     198  	gid_t gid;
     199  
     200  	if (entering(tcp)) {
     201  		tprint_arg_next();
     202  
     203  		if ((rval = TEE_FETCH_BUF_DATA(buf_data, open_session, &params)))
     204  			return rval;
     205  
     206  		tprint_struct_begin();
     207  		PRINT_FIELD_U(buf_data, buf_len);
     208  		tprint_struct_next();
     209  		tprints_field_name("buf_ptr");
     210  		tprint_struct_begin();
     211  		PRINT_FIELD_UUID(open_session, uuid);
     212  		tprint_struct_next();
     213  		PRINT_FIELD_XVAL(open_session, clnt_login,
     214  				 tee_ioctl_login_types, "TEE_IOCTL_LOGIN_???");
     215  		/*
     216  		 * tee_ioctl_open_session_arg.clnt_uuid is used to pass
     217  		 * connectionData, which is currently only used to indicate
     218  		 * which group the client application wishes to authenticate as
     219  		 * (when TEE_IOCTL_LOGIN_GROUP or TEE_IOCTL_LOGIN_GROUP_APPLICATION
     220  		 * are used).
     221  		 *
     222  		 * It is not an UUID; actual client UUID is computed in the kernel.
     223  		 */
     224  		switch (open_session.clnt_login) {
     225  		case TEE_IOCTL_LOGIN_PUBLIC:
     226  		case TEE_IOCTL_LOGIN_USER:
     227  		case TEE_IOCTL_LOGIN_APPLICATION:
     228  		case TEE_IOCTL_LOGIN_USER_APPLICATION:
     229  			break;
     230  		case TEE_IOCTL_LOGIN_GROUP:
     231  		case TEE_IOCTL_LOGIN_GROUP_APPLICATION:
     232  			memcpy(&gid, open_session.clnt_uuid, sizeof(gid));
     233  			tprint_struct_next();
     234  			tprints_field_name("clnt_uuid");
     235  			printuid(gid);
     236  			break;
     237  		default:
     238  			tprint_struct_next();
     239  			PRINT_FIELD_X_ARRAY(open_session, clnt_uuid);
     240  		}
     241  		tprint_struct_next();
     242  		PRINT_FIELD_U(open_session, cancel_id);
     243  		tprint_struct_next();
     244  		PRINT_FIELD_U(open_session, num_params);
     245  		tee_print_params(tcp, params, open_session.num_params);
     246  
     247  		tprint_struct_end();
     248  		return 0;
     249  
     250  	} else if (syserror(tcp)) {
     251  		tprint_struct_end();
     252  		return RVAL_IOCTL_DECODED;
     253  
     254  	} else {
     255  		tprint_value_changed();
     256  		/*
     257  		 * Yes, params are [in/out] for TEE_IOC_OPEN_SESSION.
     258  		 * As for all other operations they are used in.
     259  		 */
     260  		if ((rval = TEE_FETCH_BUF_DATA(buf_data, open_session, &params)))
     261  			return rval;
     262  
     263  		tprint_struct_begin();
     264  		PRINT_FIELD_SESSION(open_session, session);
     265  		tprint_struct_next();
     266  		PRINT_FIELD_U(open_session, ret);
     267  		tprint_struct_next();
     268  		PRINT_FIELD_XVAL(open_session, ret_origin, tee_ioctl_origins,
     269  				 "TEEC_ORIGIN_???");
     270  		tee_print_params(tcp, params, open_session.num_params);
     271  
     272  		tprint_struct_end();
     273  		tprint_struct_end();
     274  		return RVAL_IOCTL_DECODED;
     275  	}
     276  }
     277  
     278  static int
     279  tee_invoke(struct tcb *const tcp, const kernel_ulong_t arg)
     280  {
     281  	int rval;
     282  	struct tee_ioctl_buf_data buf_data;
     283  	struct tee_ioctl_invoke_arg invoke;
     284  	uint64_t params;
     285  
     286  	if (entering(tcp)) {
     287  		tprint_arg_next();
     288  		if ((rval = TEE_FETCH_BUF_DATA(buf_data, invoke, &params)))
     289  			return rval;
     290  
     291  		tprint_struct_begin();
     292  		PRINT_FIELD_U(buf_data, buf_len);
     293  		tprint_struct_next();
     294  		tprints_field_name("buf_ptr");
     295  		tprint_struct_begin();
     296  		PRINT_FIELD_U(invoke, func);
     297  		tprint_struct_next();
     298  		PRINT_FIELD_SESSION(invoke, session);
     299  		tprint_struct_next();
     300  		PRINT_FIELD_U(invoke, cancel_id);
     301  		tprint_struct_next();
     302  		PRINT_FIELD_U(invoke, num_params);
     303  		tee_print_params(tcp, params, invoke.num_params);
     304  
     305  		tprint_struct_end();
     306  		return 0;
     307  
     308  	} else if (syserror(tcp)) {
     309  		tprint_struct_end();
     310  		return RVAL_IOCTL_DECODED;
     311  
     312  	} else {
     313  		tprint_value_changed();
     314  		if ((rval = TEE_FETCH_BUF_DATA(buf_data, invoke, &params)))
     315  			return rval;
     316  
     317  		tprint_struct_begin();
     318  		PRINT_FIELD_U(invoke, ret);
     319  		tprint_struct_next();
     320  		PRINT_FIELD_XVAL(invoke, ret_origin, tee_ioctl_origins,
     321  				 "TEEC_ORIGIN_???");
     322  		tee_print_params(tcp, params, invoke.num_params);
     323  
     324  		tprint_struct_end();
     325  		tprint_struct_end();
     326  		return RVAL_IOCTL_DECODED;
     327  	}
     328  }
     329  
     330  static int
     331  tee_cancel(struct tcb *const tcp, const kernel_ulong_t arg)
     332  {
     333  	struct tee_ioctl_cancel_arg cancel;
     334  
     335  	tprint_arg_next();
     336  	if (umove_or_printaddr(tcp, arg, &cancel))
     337  		return RVAL_IOCTL_DECODED;
     338  
     339  	tprint_struct_begin();
     340  	PRINT_FIELD_U(cancel, cancel_id);
     341  	tprint_struct_next();
     342  	PRINT_FIELD_SESSION(cancel, session);
     343  
     344  	tprint_struct_end();
     345  	return RVAL_IOCTL_DECODED;
     346  }
     347  
     348  static int
     349  tee_close_session(struct tcb *const tcp, const kernel_ulong_t arg)
     350  {
     351  	struct tee_ioctl_close_session_arg close_session;
     352  
     353  	tprint_arg_next();
     354  	if (umove_or_printaddr(tcp, arg, &close_session))
     355  		return RVAL_IOCTL_DECODED;
     356  
     357  	tprint_struct_begin();
     358  	PRINT_FIELD_SESSION(close_session, session);
     359  
     360  	tprint_struct_end();
     361  	return RVAL_IOCTL_DECODED;
     362  }
     363  
     364  static int
     365  tee_suppl_recv(struct tcb *const tcp, const kernel_ulong_t arg)
     366  {
     367  	int rval;
     368  	struct tee_ioctl_buf_data buf_data;
     369  	struct tee_iocl_supp_recv_arg supp_recv;
     370  	uint64_t params;
     371  
     372  	if (entering(tcp)) {
     373  		tprint_arg_next();
     374  		if ((rval = TEE_FETCH_BUF_DATA(buf_data, supp_recv, &params)))
     375  			return rval;
     376  
     377  		tprint_struct_begin();
     378  		PRINT_FIELD_U(buf_data, buf_len);
     379  		tprint_struct_next();
     380  		tprints_field_name("buf_ptr");
     381  		tprint_struct_begin();
     382  		PRINT_FIELD_U(supp_recv, func);
     383  		tprint_struct_next();
     384  		PRINT_FIELD_U(supp_recv, num_params);
     385  		tee_print_params(tcp, params, supp_recv.num_params);
     386  
     387  		tprint_struct_end();
     388  		return 0;
     389  
     390  	} else if (syserror(tcp)) {
     391  		tprint_struct_end();
     392  		return RVAL_IOCTL_DECODED;
     393  
     394  	} else {
     395  		tprint_value_changed();
     396  		if ((rval = TEE_FETCH_BUF_DATA(buf_data, supp_recv, &params)))
     397  			return rval;
     398  
     399  		/* num_params is [in/out] for TEE_IOC_SUPPL_RECV only */
     400  		tprint_struct_begin();
     401  		PRINT_FIELD_U(supp_recv, num_params);
     402  		tee_print_params(tcp, params, supp_recv.num_params);
     403  
     404  		tprint_struct_end();
     405  		tprint_struct_end();
     406  		return RVAL_IOCTL_DECODED;
     407  	}
     408  }
     409  
     410  static int
     411  tee_suppl_send(struct tcb *const tcp, const kernel_ulong_t arg)
     412  {
     413  	int rval;
     414  	struct tee_ioctl_buf_data buf_data;
     415  	struct tee_iocl_supp_send_arg supp_send;
     416  	uint64_t params;
     417  
     418  	if (entering(tcp)) {
     419  		tprint_arg_next();
     420  		if ((rval = TEE_FETCH_BUF_DATA(buf_data, supp_send, &params)))
     421  			return rval;
     422  
     423  		tprint_struct_begin();
     424  		PRINT_FIELD_U(buf_data, buf_len);
     425  		tprint_struct_next();
     426  		tprints_field_name("buf_ptr");
     427  		tprint_struct_begin();
     428  		PRINT_FIELD_U(supp_send, num_params);
     429  		tee_print_params(tcp, params, supp_send.num_params);
     430  
     431  		tprint_struct_end();
     432  		return 0;
     433  
     434  	} else if (syserror(tcp)) {
     435  		tprint_struct_end();
     436  		return RVAL_IOCTL_DECODED;
     437  
     438  	} else {
     439  		tprint_value_changed();
     440  		if ((rval = TEE_FETCH_BUF_DATA(buf_data, supp_send, &params)))
     441  			return rval;
     442  
     443  		tprint_struct_begin();
     444  		PRINT_FIELD_U(supp_send, ret);
     445  		tee_print_params(tcp, params, supp_send.num_params);
     446  
     447  		tprint_struct_end();
     448  		tprint_struct_end();
     449  		return RVAL_IOCTL_DECODED;
     450  	}
     451  }
     452  
     453  static int
     454  tee_shm_alloc(struct tcb *const tcp, const kernel_ulong_t arg)
     455  {
     456  	struct tee_ioctl_shm_alloc_data shm_alloc;
     457  
     458  	if (entering(tcp)) {
     459  		tprint_arg_next();
     460  		if (umove_or_printaddr(tcp, arg, &shm_alloc))
     461  			return RVAL_IOCTL_DECODED;
     462  
     463  		tprint_struct_begin();
     464  		PRINT_FIELD_X(shm_alloc, size);
     465  		tprint_struct_next();
     466  		PRINT_FIELD_FLAGS(shm_alloc, flags,
     467  				  tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
     468  		tprint_struct_end();
     469  		return 0;
     470  
     471  	} else if (syserror(tcp)) {
     472  		return RVAL_IOCTL_DECODED;
     473  
     474  	} else {
     475  		tprint_value_changed();
     476  		if (umove_or_printaddr(tcp, arg, &shm_alloc))
     477  			return RVAL_IOCTL_DECODED;
     478  
     479  		tprint_struct_begin();
     480  		PRINT_FIELD_X(shm_alloc, size);
     481  		tprint_struct_next();
     482  		PRINT_FIELD_FLAGS(shm_alloc, flags,
     483  				  tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
     484  		tprint_struct_next();
     485  		PRINT_FIELD_D(shm_alloc, id);
     486  
     487  		tprint_struct_end();
     488  		return RVAL_IOCTL_DECODED;
     489  	}
     490  }
     491  
     492  static int
     493  tee_shm_register_fd(struct tcb *const tcp, const kernel_ulong_t arg)
     494  {
     495  	struct tee_ioctl_shm_register_fd_data shm_register_fd;
     496  
     497  	if (entering(tcp)) {
     498  		tprint_arg_next();
     499  		if (umove_or_printaddr(tcp, arg, &shm_register_fd))
     500  			return RVAL_IOCTL_DECODED;
     501  
     502  		tprint_struct_begin();
     503  		PRINT_FIELD_FD(shm_register_fd, fd, tcp);
     504  		tprint_struct_next();
     505  		PRINT_FIELD_FLAGS(shm_register_fd, flags,
     506  				  tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
     507  		tprint_struct_end();
     508  		return 0;
     509  
     510  	} else if (syserror(tcp)) {
     511  		return RVAL_IOCTL_DECODED;
     512  
     513  	} else {
     514  		tprint_value_changed();
     515  		if (umove_or_printaddr(tcp, arg, &shm_register_fd))
     516  			return RVAL_IOCTL_DECODED;
     517  
     518  		tprint_struct_begin();
     519  		PRINT_FIELD_X(shm_register_fd, size);
     520  		tprint_struct_next();
     521  		PRINT_FIELD_D(shm_register_fd, id);
     522  
     523  		tprint_struct_end();
     524  		return RVAL_IOCTL_DECODED;
     525  	}
     526  }
     527  
     528  static int
     529  tee_shm_register(struct tcb *const tcp, const kernel_ulong_t arg)
     530  {
     531  	struct tee_ioctl_shm_register_data shm_register;
     532  
     533  	if (entering(tcp)) {
     534  		tprint_arg_next();
     535  		if (umove_or_printaddr(tcp, arg, &shm_register))
     536  			return RVAL_IOCTL_DECODED;
     537  
     538  		tprint_struct_begin();
     539  		PRINT_FIELD_ADDR64(shm_register, addr);
     540  		tprint_struct_next();
     541  		PRINT_FIELD_X(shm_register, length);
     542  		tprint_struct_next();
     543  		PRINT_FIELD_FLAGS(shm_register, flags,
     544  				  tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
     545  		tprint_struct_end();
     546  		return 0;
     547  
     548  	} else if (syserror(tcp)) {
     549  		return RVAL_IOCTL_DECODED;
     550  
     551  	} else {
     552  		tprint_value_changed();
     553  		if (umove_or_printaddr(tcp, arg, &shm_register))
     554  			return RVAL_IOCTL_DECODED;
     555  
     556  		tprint_struct_begin();
     557  		PRINT_FIELD_X(shm_register, length);
     558  		tprint_struct_next();
     559  		PRINT_FIELD_FLAGS(shm_register, flags,
     560  				  tee_ioctl_shm_flags, "TEE_IOCTL_SHM_???");
     561  		tprint_struct_next();
     562  		PRINT_FIELD_D(shm_register, id);
     563  
     564  		tprint_struct_end();
     565  		return RVAL_IOCTL_DECODED;
     566  	}
     567  }
     568  
     569  int
     570  tee_ioctl(struct tcb *const tcp, const unsigned int code,
     571  	  const kernel_ulong_t arg)
     572  {
     573  	switch (code) {
     574  	case TEE_IOC_VERSION:
     575  		return tee_version(tcp, arg);
     576  
     577  	case TEE_IOC_OPEN_SESSION:
     578  		return tee_open_session(tcp, arg);
     579  
     580  	case TEE_IOC_INVOKE:
     581  		return tee_invoke(tcp, arg);
     582  
     583  	case TEE_IOC_CANCEL:
     584  		return tee_cancel(tcp, arg);
     585  
     586  	case TEE_IOC_CLOSE_SESSION:
     587  		return tee_close_session(tcp, arg);
     588  
     589  	case TEE_IOC_SUPPL_RECV:
     590  		return tee_suppl_recv(tcp, arg);
     591  
     592  	case TEE_IOC_SUPPL_SEND:
     593  		return tee_suppl_send(tcp, arg);
     594  
     595  	case TEE_IOC_SHM_ALLOC:
     596  		return tee_shm_alloc(tcp, arg);
     597  
     598  	case TEE_IOC_SHM_REGISTER_FD:
     599  		/* This one isn't upstream */
     600  		return tee_shm_register_fd(tcp, arg);
     601  
     602  	case TEE_IOC_SHM_REGISTER:
     603  		return tee_shm_register(tcp, arg);
     604  
     605  	default:
     606  		return RVAL_DECODED;
     607  	}
     608  }