~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/include/asm/uaccess.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #ifndef _ARCH_POWERPC_UACCESS_H
  3 #define _ARCH_POWERPC_UACCESS_H
  4 
  5 #include <asm/processor.h>
  6 #include <asm/page.h>
  7 #include <asm/extable.h>
  8 #include <asm/kup.h>
  9 
 10 #ifdef __powerpc64__
 11 /* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */
 12 #define TASK_SIZE_MAX           TASK_SIZE_USER64
 13 #endif
 14 
 15 #include <asm-generic/access_ok.h>
 16 
 17 /*
 18  * These are the main single-value transfer routines.  They automatically
 19  * use the right size if we just have the right pointer type.
 20  *
 21  * This gets kind of ugly. We want to return _two_ values in "get_user()"
 22  * and yet we don't want to do any pointers, because that is too much
 23  * of a performance impact. Thus we have a few rather ugly macros here,
 24  * and hide all the ugliness from the user.
 25  *
 26  * The "__xxx" versions of the user access functions are versions that
 27  * do not verify the address space, that must have been done previously
 28  * with a separate "access_ok()" call (this is used when we do multiple
 29  * accesses to the same area of user memory).
 30  *
 31  * As we use the same address space for kernel and user data on the
 32  * PowerPC, we can just do these as direct assignments.  (Of course, the
 33  * exception handling means that it's no longer "just"...)
 34  *
 35  */
 36 #define __put_user(x, ptr)                                      \
 37 ({                                                              \
 38         long __pu_err;                                          \
 39         __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
 40         __typeof__(*(ptr)) __pu_val = (__typeof__(*(ptr)))(x);  \
 41         __typeof__(sizeof(*(ptr))) __pu_size = sizeof(*(ptr));  \
 42                                                                 \
 43         might_fault();                                          \
 44         do {                                                    \
 45                 __label__ __pu_failed;                          \
 46                                                                 \
 47                 allow_write_to_user(__pu_addr, __pu_size);      \
 48                 __put_user_size_goto(__pu_val, __pu_addr, __pu_size, __pu_failed);      \
 49                 prevent_write_to_user(__pu_addr, __pu_size);    \
 50                 __pu_err = 0;                                   \
 51                 break;                                          \
 52                                                                 \
 53 __pu_failed:                                                    \
 54                 prevent_write_to_user(__pu_addr, __pu_size);    \
 55                 __pu_err = -EFAULT;                             \
 56         } while (0);                                            \
 57                                                                 \
 58         __pu_err;                                               \
 59 })
 60 
 61 #define put_user(x, ptr)                                                \
 62 ({                                                                      \
 63         __typeof__(*(ptr)) __user *_pu_addr = (ptr);                    \
 64                                                                         \
 65         access_ok(_pu_addr, sizeof(*(ptr))) ?                           \
 66                   __put_user(x, _pu_addr) : -EFAULT;                    \
 67 })
 68 
 69 /*
 70  * We don't tell gcc that we are accessing memory, but this is OK
 71  * because we do not write to any memory gcc knows about, so there
 72  * are no aliasing issues.
 73  */
 74 /* -mprefixed can generate offsets beyond range, fall back hack */
 75 #ifdef CONFIG_PPC_KERNEL_PREFIXED
 76 #define __put_user_asm_goto(x, addr, label, op)                 \
 77         asm goto(                                       \
 78                 "1:     " op " %0,0(%1) # put_user\n"           \
 79                 EX_TABLE(1b, %l2)                               \
 80                 :                                               \
 81                 : "r" (x), "b" (addr)                           \
 82                 :                                               \
 83                 : label)
 84 #else
 85 #define __put_user_asm_goto(x, addr, label, op)                 \
 86         asm goto(                                       \
 87                 "1:     " op "%U1%X1 %0,%1      # put_user\n"   \
 88                 EX_TABLE(1b, %l2)                               \
 89                 :                                               \
 90                 : "r" (x), "m<>" (*addr)                        \
 91                 :                                               \
 92                 : label)
 93 #endif
 94 
 95 #ifdef CONFIG_CC_IS_CLANG
 96 #define DS_FORM_CONSTRAINT "Z<>"
 97 #else
 98 #define DS_FORM_CONSTRAINT "YZ<>"
 99 #endif
100 
101 #ifdef __powerpc64__
102 #ifdef CONFIG_PPC_KERNEL_PREFIXED
103 #define __put_user_asm2_goto(x, ptr, label)                     \
104         __put_user_asm_goto(x, ptr, label, "std")
105 #else
106 #define __put_user_asm2_goto(x, addr, label)                    \
107         asm goto ("1: std%U1%X1 %0,%1   # put_user\n"           \
108                 EX_TABLE(1b, %l2)                               \
109                 :                                               \
110                 : "r" (x), DS_FORM_CONSTRAINT (*addr)           \
111                 :                                               \
112                 : label)
113 #endif // CONFIG_PPC_KERNEL_PREFIXED
114 #else /* __powerpc64__ */
115 #define __put_user_asm2_goto(x, addr, label)                    \
116         asm goto(                                       \
117                 "1:     stw%X1 %0, %1\n"                        \
118                 "2:     stw%X1 %L0, %L1\n"                      \
119                 EX_TABLE(1b, %l2)                               \
120                 EX_TABLE(2b, %l2)                               \
121                 :                                               \
122                 : "r" (x), "m" (*addr)                          \
123                 :                                               \
124                 : label)
125 #endif /* __powerpc64__ */
126 
127 #define __put_user_size_goto(x, ptr, size, label)               \
128 do {                                                            \
129         __typeof__(*(ptr)) __user *__pus_addr = (ptr);          \
130                                                                 \
131         switch (size) {                                         \
132         case 1: __put_user_asm_goto(x, __pus_addr, label, "stb"); break;        \
133         case 2: __put_user_asm_goto(x, __pus_addr, label, "sth"); break;        \
134         case 4: __put_user_asm_goto(x, __pus_addr, label, "stw"); break;        \
135         case 8: __put_user_asm2_goto(x, __pus_addr, label); break;              \
136         default: BUILD_BUG();                                   \
137         }                                                       \
138 } while (0)
139 
140 /*
141  * This does an atomic 128 byte aligned load from userspace.
142  * Upto caller to do enable_kernel_vmx() before calling!
143  */
144 #define __get_user_atomic_128_aligned(kaddr, uaddr, err)                \
145         __asm__ __volatile__(                           \
146                 ".machine push\n"                       \
147                 ".machine altivec\n"                    \
148                 "1:     lvx  0,0,%1     # get user\n"   \
149                 "       stvx 0,0,%2     # put kernel\n" \
150                 ".machine pop\n"                        \
151                 "2:\n"                                  \
152                 ".section .fixup,\"ax\"\n"              \
153                 "3:     li %0,%3\n"                     \
154                 "       b 2b\n"                         \
155                 ".previous\n"                           \
156                 EX_TABLE(1b, 3b)                        \
157                 : "=r" (err)                    \
158                 : "b" (uaddr), "b" (kaddr), "i" (-EFAULT), "" (err))
159 
160 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
161 
162 /* -mprefixed can generate offsets beyond range, fall back hack */
163 #ifdef CONFIG_PPC_KERNEL_PREFIXED
164 #define __get_user_asm_goto(x, addr, label, op)                 \
165         asm_goto_output(                                        \
166                 "1:     "op" %0,0(%1)   # get_user\n"           \
167                 EX_TABLE(1b, %l2)                               \
168                 : "=r" (x)                                      \
169                 : "b" (addr)                                    \
170                 :                                               \
171                 : label)
172 #else
173 #define __get_user_asm_goto(x, addr, label, op)                 \
174         asm_goto_output(                                        \
175                 "1:     "op"%U1%X1 %0, %1       # get_user\n"   \
176                 EX_TABLE(1b, %l2)                               \
177                 : "=r" (x)                                      \
178                 : "m<>" (*addr)                                 \
179                 :                                               \
180                 : label)
181 #endif
182 
183 #ifdef __powerpc64__
184 #ifdef CONFIG_PPC_KERNEL_PREFIXED
185 #define __get_user_asm2_goto(x, addr, label)                    \
186         __get_user_asm_goto(x, addr, label, "ld")
187 #else
188 #define __get_user_asm2_goto(x, addr, label)                    \
189         asm_goto_output(                                        \
190                 "1:     ld%U1%X1 %0, %1 # get_user\n"           \
191                 EX_TABLE(1b, %l2)                               \
192                 : "=r" (x)                                      \
193                 : DS_FORM_CONSTRAINT (*addr)                    \
194                 :                                               \
195                 : label)
196 #endif // CONFIG_PPC_KERNEL_PREFIXED
197 #else /* __powerpc64__ */
198 #define __get_user_asm2_goto(x, addr, label)                    \
199         asm_goto_output(                                        \
200                 "1:     lwz%X1 %0, %1\n"                        \
201                 "2:     lwz%X1 %L0, %L1\n"                      \
202                 EX_TABLE(1b, %l2)                               \
203                 EX_TABLE(2b, %l2)                               \
204                 : "=&r" (x)                                     \
205                 : "m" (*addr)                                   \
206                 :                                               \
207                 : label)
208 #endif /* __powerpc64__ */
209 
210 #define __get_user_size_goto(x, ptr, size, label)                               \
211 do {                                                                            \
212         BUILD_BUG_ON(size > sizeof(x));                                         \
213         switch (size) {                                                         \
214         case 1: __get_user_asm_goto(x, (u8 __user *)ptr, label, "lbz"); break;  \
215         case 2: __get_user_asm_goto(x, (u16 __user *)ptr, label, "lhz"); break; \
216         case 4: __get_user_asm_goto(x, (u32 __user *)ptr, label, "lwz"); break; \
217         case 8: __get_user_asm2_goto(x, (u64 __user *)ptr, label);  break;      \
218         default: x = 0; BUILD_BUG();                                            \
219         }                                                                       \
220 } while (0)
221 
222 #define __get_user_size_allowed(x, ptr, size, retval)                   \
223 do {                                                                    \
224                 __label__ __gus_failed;                                 \
225                                                                         \
226                 __get_user_size_goto(x, ptr, size, __gus_failed);       \
227                 retval = 0;                                             \
228                 break;                                                  \
229 __gus_failed:                                                           \
230                 x = 0;                                                  \
231                 retval = -EFAULT;                                       \
232 } while (0)
233 
234 #else /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
235 
236 #define __get_user_asm(x, addr, err, op)                \
237         __asm__ __volatile__(                           \
238                 "1:     "op"%U2%X2 %1, %2       # get_user\n"   \
239                 "2:\n"                                  \
240                 ".section .fixup,\"ax\"\n"              \
241                 "3:     li %0,%3\n"                     \
242                 "       li %1,0\n"                      \
243                 "       b 2b\n"                         \
244                 ".previous\n"                           \
245                 EX_TABLE(1b, 3b)                        \
246                 : "=r" (err), "=r" (x)                  \
247                 : "m<>" (*addr), "i" (-EFAULT), "" (err))
248 
249 #ifdef __powerpc64__
250 #define __get_user_asm2(x, addr, err)                   \
251         __get_user_asm(x, addr, err, "ld")
252 #else /* __powerpc64__ */
253 #define __get_user_asm2(x, addr, err)                   \
254         __asm__ __volatile__(                           \
255                 "1:     lwz%X2 %1, %2\n"                        \
256                 "2:     lwz%X2 %L1, %L2\n"              \
257                 "3:\n"                                  \
258                 ".section .fixup,\"ax\"\n"              \
259                 "4:     li %0,%3\n"                     \
260                 "       li %1,0\n"                      \
261                 "       li %1+1,0\n"                    \
262                 "       b 3b\n"                         \
263                 ".previous\n"                           \
264                 EX_TABLE(1b, 4b)                        \
265                 EX_TABLE(2b, 4b)                        \
266                 : "=r" (err), "=&r" (x)                 \
267                 : "m" (*addr), "i" (-EFAULT), "" (err))
268 #endif /* __powerpc64__ */
269 
270 #define __get_user_size_allowed(x, ptr, size, retval)           \
271 do {                                                            \
272         retval = 0;                                             \
273         BUILD_BUG_ON(size > sizeof(x));                         \
274         switch (size) {                                         \
275         case 1: __get_user_asm(x, (u8 __user *)ptr, retval, "lbz"); break;      \
276         case 2: __get_user_asm(x, (u16 __user *)ptr, retval, "lhz"); break;     \
277         case 4: __get_user_asm(x, (u32 __user *)ptr, retval, "lwz"); break;     \
278         case 8: __get_user_asm2(x, (u64 __user *)ptr, retval);  break;  \
279         default: x = 0; BUILD_BUG();                            \
280         }                                                       \
281 } while (0)
282 
283 #define __get_user_size_goto(x, ptr, size, label)               \
284 do {                                                            \
285         long __gus_retval;                                      \
286                                                                 \
287         __get_user_size_allowed(x, ptr, size, __gus_retval);    \
288         if (__gus_retval)                                       \
289                 goto label;                                     \
290 } while (0)
291 
292 #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
293 
294 /*
295  * This is a type: either unsigned long, if the argument fits into
296  * that type, or otherwise unsigned long long.
297  */
298 #define __long_type(x) \
299         __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
300 
301 #define __get_user(x, ptr)                                      \
302 ({                                                              \
303         long __gu_err;                                          \
304         __long_type(*(ptr)) __gu_val;                           \
305         __typeof__(*(ptr)) __user *__gu_addr = (ptr);   \
306         __typeof__(sizeof(*(ptr))) __gu_size = sizeof(*(ptr));  \
307                                                                 \
308         might_fault();                                  \
309         allow_read_from_user(__gu_addr, __gu_size);             \
310         __get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err);      \
311         prevent_read_from_user(__gu_addr, __gu_size);           \
312         (x) = (__typeof__(*(ptr)))__gu_val;                     \
313                                                                 \
314         __gu_err;                                               \
315 })
316 
317 #define get_user(x, ptr)                                                \
318 ({                                                                      \
319         __typeof__(*(ptr)) __user *_gu_addr = (ptr);                    \
320                                                                         \
321         access_ok(_gu_addr, sizeof(*(ptr))) ?                           \
322                   __get_user(x, _gu_addr) :                             \
323                   ((x) = (__force __typeof__(*(ptr)))0, -EFAULT);       \
324 })
325 
326 /* more complex routines */
327 
328 extern unsigned long __copy_tofrom_user(void __user *to,
329                 const void __user *from, unsigned long size);
330 
331 #ifdef __powerpc64__
332 static inline unsigned long
333 raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
334 {
335         unsigned long ret;
336 
337         allow_read_write_user(to, from, n);
338         ret = __copy_tofrom_user(to, from, n);
339         prevent_read_write_user(to, from, n);
340         return ret;
341 }
342 #endif /* __powerpc64__ */
343 
344 static inline unsigned long raw_copy_from_user(void *to,
345                 const void __user *from, unsigned long n)
346 {
347         unsigned long ret;
348 
349         allow_read_from_user(from, n);
350         ret = __copy_tofrom_user((__force void __user *)to, from, n);
351         prevent_read_from_user(from, n);
352         return ret;
353 }
354 
355 static inline unsigned long
356 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
357 {
358         unsigned long ret;
359 
360         allow_write_to_user(to, n);
361         ret = __copy_tofrom_user(to, (__force const void __user *)from, n);
362         prevent_write_to_user(to, n);
363         return ret;
364 }
365 
366 unsigned long __arch_clear_user(void __user *addr, unsigned long size);
367 
368 static inline unsigned long __clear_user(void __user *addr, unsigned long size)
369 {
370         unsigned long ret;
371 
372         might_fault();
373         allow_write_to_user(addr, size);
374         ret = __arch_clear_user(addr, size);
375         prevent_write_to_user(addr, size);
376         return ret;
377 }
378 
379 static inline unsigned long clear_user(void __user *addr, unsigned long size)
380 {
381         return likely(access_ok(addr, size)) ? __clear_user(addr, size) : size;
382 }
383 
384 extern long strncpy_from_user(char *dst, const char __user *src, long count);
385 extern __must_check long strnlen_user(const char __user *str, long n);
386 
387 #ifdef CONFIG_ARCH_HAS_COPY_MC
388 unsigned long __must_check
389 copy_mc_generic(void *to, const void *from, unsigned long size);
390 
391 static inline unsigned long __must_check
392 copy_mc_to_kernel(void *to, const void *from, unsigned long size)
393 {
394         return copy_mc_generic(to, from, size);
395 }
396 #define copy_mc_to_kernel copy_mc_to_kernel
397 
398 static inline unsigned long __must_check
399 copy_mc_to_user(void __user *to, const void *from, unsigned long n)
400 {
401         if (check_copy_size(from, n, true)) {
402                 if (access_ok(to, n)) {
403                         allow_write_to_user(to, n);
404                         n = copy_mc_generic((void __force *)to, from, n);
405                         prevent_write_to_user(to, n);
406                 }
407         }
408 
409         return n;
410 }
411 #endif
412 
413 extern long __copy_from_user_flushcache(void *dst, const void __user *src,
414                 unsigned size);
415 
416 static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len)
417 {
418         if (unlikely(!access_ok(ptr, len)))
419                 return false;
420 
421         might_fault();
422 
423         allow_read_write_user((void __user *)ptr, ptr, len);
424         return true;
425 }
426 #define user_access_begin       user_access_begin
427 #define user_access_end         prevent_current_access_user
428 #define user_access_save        prevent_user_access_return
429 #define user_access_restore     restore_user_access
430 
431 static __must_check __always_inline bool
432 user_read_access_begin(const void __user *ptr, size_t len)
433 {
434         if (unlikely(!access_ok(ptr, len)))
435                 return false;
436 
437         might_fault();
438 
439         allow_read_from_user(ptr, len);
440         return true;
441 }
442 #define user_read_access_begin  user_read_access_begin
443 #define user_read_access_end            prevent_current_read_from_user
444 
445 static __must_check __always_inline bool
446 user_write_access_begin(const void __user *ptr, size_t len)
447 {
448         if (unlikely(!access_ok(ptr, len)))
449                 return false;
450 
451         might_fault();
452 
453         allow_write_to_user((void __user *)ptr, len);
454         return true;
455 }
456 #define user_write_access_begin user_write_access_begin
457 #define user_write_access_end           prevent_current_write_to_user
458 
459 #define unsafe_get_user(x, p, e) do {                                   \
460         __long_type(*(p)) __gu_val;                             \
461         __typeof__(*(p)) __user *__gu_addr = (p);               \
462                                                                 \
463         __get_user_size_goto(__gu_val, __gu_addr, sizeof(*(p)), e); \
464         (x) = (__typeof__(*(p)))__gu_val;                       \
465 } while (0)
466 
467 #define unsafe_put_user(x, p, e) \
468         __put_user_size_goto((__typeof__(*(p)))(x), (p), sizeof(*(p)), e)
469 
470 #define unsafe_copy_from_user(d, s, l, e) \
471 do {                                                                                    \
472         u8 *_dst = (u8 *)(d);                                                           \
473         const u8 __user *_src = (const u8 __user *)(s);                                 \
474         size_t _len = (l);                                                              \
475         int _i;                                                                         \
476                                                                                         \
477         for (_i = 0; _i < (_len & ~(sizeof(u64) - 1)); _i += sizeof(u64))               \
478                 unsafe_get_user(*(u64 *)(_dst + _i), (u64 __user *)(_src + _i), e);     \
479         if (_len & 4) {                                                                 \
480                 unsafe_get_user(*(u32 *)(_dst + _i), (u32 __user *)(_src + _i), e);     \
481                 _i += 4;                                                                \
482         }                                                                               \
483         if (_len & 2) {                                                                 \
484                 unsafe_get_user(*(u16 *)(_dst + _i), (u16 __user *)(_src + _i), e);     \
485                 _i += 2;                                                                \
486         }                                                                               \
487         if (_len & 1)                                                                   \
488                 unsafe_get_user(*(u8 *)(_dst + _i), (u8 __user *)(_src + _i), e);       \
489 } while (0)
490 
491 #define unsafe_copy_to_user(d, s, l, e) \
492 do {                                                                    \
493         u8 __user *_dst = (u8 __user *)(d);                             \
494         const u8 *_src = (const u8 *)(s);                               \
495         size_t _len = (l);                                              \
496         int _i;                                                         \
497                                                                         \
498         for (_i = 0; _i < (_len & ~(sizeof(u64) - 1)); _i += sizeof(u64))       \
499                 unsafe_put_user(*(u64 *)(_src + _i), (u64 __user *)(_dst + _i), e); \
500         if (_len & 4) {                                                 \
501                 unsafe_put_user(*(u32*)(_src + _i), (u32 __user *)(_dst + _i), e); \
502                 _i += 4;                                                \
503         }                                                               \
504         if (_len & 2) {                                                 \
505                 unsafe_put_user(*(u16*)(_src + _i), (u16 __user *)(_dst + _i), e); \
506                 _i += 2;                                                \
507         }                                                               \
508         if (_len & 1) \
509                 unsafe_put_user(*(u8*)(_src + _i), (u8 __user *)(_dst + _i), e); \
510 } while (0)
511 
512 #define __get_kernel_nofault(dst, src, type, err_label)                 \
513         __get_user_size_goto(*((type *)(dst)),                          \
514                 (__force type __user *)(src), sizeof(type), err_label)
515 
516 #define __put_kernel_nofault(dst, src, type, err_label)                 \
517         __put_user_size_goto(*((type *)(src)),                          \
518                 (__force type __user *)(dst), sizeof(type), err_label)
519 
520 #endif  /* _ARCH_POWERPC_UACCESS_H */
521 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php