1 /*
2  * Copyright (c) 2016, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <errno.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <tee_client_api.h>
36 #include <tee_supplicant.h>
37 #include "prof.h"
38 
39 #ifndef __aligned
40 #define __aligned(x) __attribute__((__aligned__(x)))
41 #endif
42 #include <linux/tee.h>
43 
prof_process(size_t num_params,struct tee_ioctl_param * params,const char * prefix)44 TEEC_Result prof_process(size_t num_params, struct tee_ioctl_param *params,
45 			 const char *prefix)
46 {
47 	char vers[5] = "";
48 	char path[255] = { 0 };
49 	size_t bufsize = 0;
50 	TEEC_UUID *u = NULL;
51 	int fd = -1;
52 	void *buf = NULL;
53 	int flags = 0;
54 	int id = 0;
55 	int st = 0;
56 	int n = 0;
57 
58 	if (num_params != 3 ||
59 	    (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
60 		TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT ||
61 	    (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
62 		TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
63 	    (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
64 		TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT)
65 		return TEEC_ERROR_BAD_PARAMETERS;
66 
67 	id = params[0].a;
68 
69 	if (MEMREF_SIZE(params + 1) != sizeof(TEEC_UUID))
70 		return TEEC_ERROR_BAD_PARAMETERS;
71 
72 	u = tee_supp_param_to_va(params + 1);
73 	if (!u)
74 		return TEEC_ERROR_BAD_PARAMETERS;
75 
76 	buf = tee_supp_param_to_va(params + 2);
77 	if (!buf)
78 		return TEEC_ERROR_BAD_PARAMETERS;
79 
80 	bufsize = MEMREF_SIZE(params + 2);
81 
82 	if (id < 0 || id > 100)
83 		return TEEC_ERROR_BAD_PARAMETERS;
84 
85 	flags = O_APPEND | O_WRONLY;
86 	if (!id) {
87 		/* id == 0 means create file */
88 		flags |= O_CREAT | O_EXCL;
89 		id = 1;
90 	}
91 
92 	for (;;) {
93 		if (id > 1) {
94 			/*
95 			 * id == 1 is file 0 (no suffix), id == 2 is file .1
96 			 * etc.
97 			 */
98 			if (id > 100)
99 				id = 100; /* Avoid GCC truncation warning */
100 			snprintf(vers, sizeof(vers), ".%d", id - 1);
101 		}
102 		n = snprintf(path, sizeof(path),
103 			"/tmp/%s"
104 			"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
105 			"%s.out",
106 			prefix,
107 			u->timeLow, u->timeMid, u->timeHiAndVersion,
108 			u->clockSeqAndNode[0], u->clockSeqAndNode[1],
109 			u->clockSeqAndNode[2], u->clockSeqAndNode[3],
110 			u->clockSeqAndNode[4], u->clockSeqAndNode[5],
111 			u->clockSeqAndNode[6], u->clockSeqAndNode[7],
112 			vers);
113 		if ((n < 0) || (n >= (int)sizeof(path)))
114 			break;
115 		fd = open(path, flags, 0644);
116 		if (fd >= 0) {
117 			do {
118 				st = write(fd, buf, bufsize);
119 			} while (st < 0 && errno == EINTR);
120 			close(fd);
121 			if (st < 0 || st != (int)bufsize)
122 				break;
123 			params[0].a = id;
124 			goto success;
125 		}
126 		if (errno != EEXIST)
127 			break;
128 		if (id++ == 100)
129 			break;
130 	}
131 
132 	/* An error occurred */
133 	return TEEC_ERROR_GENERIC;
134 
135 success:
136 	return TEEC_SUCCESS;
137 }
138