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

TOMOYO Linux Cross Reference
Linux/fs/ntfs3/record.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ 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.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /fs/ntfs3/record.c (Version linux-6.12-rc7) and /fs/ntfs3/record.c (Version linux-2.6.32.71)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  *                                                
  4  * Copyright (C) 2019-2021 Paragon Software Gm    
  5  *                                                
  6  */                                               
  7                                                   
  8 #include <linux/fs.h>                             
  9                                                   
 10 #include "debug.h"                                
 11 #include "ntfs.h"                                 
 12 #include "ntfs_fs.h"                              
 13                                                   
 14 static inline int compare_attr(const struct AT    
 15                                const __le16 *n    
 16                                const u16 *upca    
 17 {                                                 
 18         /* First, compare the type codes. */      
 19         int diff = le32_to_cpu(left->type) - l    
 20                                                   
 21         if (diff)                                 
 22                 return diff;                      
 23                                                   
 24         /* They have the same type code, so we    
 25         return ntfs_cmp_names(attr_name(left),    
 26                               upcase, true);      
 27 }                                                 
 28                                                   
 29 /*                                                
 30  * mi_new_attt_id                                 
 31  *                                                
 32  * Return: Unused attribute id that is less th    
 33  */                                               
 34 static __le16 mi_new_attt_id(struct mft_inode     
 35 {                                                 
 36         u16 free_id, max_id, t16;                 
 37         struct MFT_REC *rec = mi->mrec;           
 38         struct ATTRIB *attr;                      
 39         __le16 id;                                
 40                                                   
 41         id = rec->next_attr_id;                   
 42         free_id = le16_to_cpu(id);                
 43         if (free_id < 0x7FFF) {                   
 44                 rec->next_attr_id = cpu_to_le1    
 45                 return id;                        
 46         }                                         
 47                                                   
 48         /* One record can store up to 1024/24     
 49         free_id = 0;                              
 50         max_id = 0;                               
 51                                                   
 52         attr = NULL;                              
 53                                                   
 54         for (;;) {                                
 55                 attr = mi_enum_attr(mi, attr);    
 56                 if (!attr) {                      
 57                         rec->next_attr_id = cp    
 58                         mi->dirty = true;         
 59                         return cpu_to_le16(fre    
 60                 }                                 
 61                                                   
 62                 t16 = le16_to_cpu(attr->id);      
 63                 if (t16 == free_id) {             
 64                         free_id += 1;             
 65                         attr = NULL;              
 66                 } else if (max_id < t16)          
 67                         max_id = t16;             
 68         }                                         
 69 }                                                 
 70                                                   
 71 int mi_get(struct ntfs_sb_info *sbi, CLST rno,    
 72 {                                                 
 73         int err;                                  
 74         struct mft_inode *m = kzalloc(sizeof(s    
 75                                                   
 76         if (!m)                                   
 77                 return -ENOMEM;                   
 78                                                   
 79         err = mi_init(m, sbi, rno);               
 80         if (err) {                                
 81                 kfree(m);                         
 82                 return err;                       
 83         }                                         
 84                                                   
 85         err = mi_read(m, false);                  
 86         if (err) {                                
 87                 mi_put(m);                        
 88                 return err;                       
 89         }                                         
 90                                                   
 91         *mi = m;                                  
 92         return 0;                                 
 93 }                                                 
 94                                                   
 95 void mi_put(struct mft_inode *mi)                 
 96 {                                                 
 97         mi_clear(mi);                             
 98         kfree(mi);                                
 99 }                                                 
100                                                   
101 int mi_init(struct mft_inode *mi, struct ntfs_    
102 {                                                 
103         mi->sbi = sbi;                            
104         mi->rno = rno;                            
105         mi->mrec = kmalloc(sbi->record_size, G    
106         if (!mi->mrec)                            
107                 return -ENOMEM;                   
108                                                   
109         return 0;                                 
110 }                                                 
111                                                   
112 /*                                                
113  * mi_read - Read MFT data.                       
114  */                                               
115 int mi_read(struct mft_inode *mi, bool is_mft)    
116 {                                                 
117         int err;                                  
118         struct MFT_REC *rec = mi->mrec;           
119         struct ntfs_sb_info *sbi = mi->sbi;       
120         u32 bpr = sbi->record_size;               
121         u64 vbo = (u64)mi->rno << sbi->record_    
122         struct ntfs_inode *mft_ni = sbi->mft.n    
123         struct runs_tree *run = mft_ni ? &mft_    
124         struct rw_semaphore *rw_lock = NULL;      
125                                                   
126         if (is_mounted(sbi)) {                    
127                 if (!is_mft && mft_ni) {          
128                         rw_lock = &mft_ni->fil    
129                         down_read(rw_lock);       
130                 }                                 
131         }                                         
132                                                   
133         err = ntfs_read_bh(sbi, run, vbo, &rec    
134         if (rw_lock)                              
135                 up_read(rw_lock);                 
136         if (!err)                                 
137                 goto ok;                          
138                                                   
139         if (err == -E_NTFS_FIXUP) {               
140                 mi->dirty = true;                 
141                 goto ok;                          
142         }                                         
143                                                   
144         if (err != -ENOENT)                       
145                 goto out;                         
146                                                   
147         if (rw_lock) {                            
148                 ni_lock(mft_ni);                  
149                 down_write(rw_lock);              
150         }                                         
151         err = attr_load_runs_vcn(mft_ni, ATTR_    
152                                  vbo >> sbi->c    
153         if (rw_lock) {                            
154                 up_write(rw_lock);                
155                 ni_unlock(mft_ni);                
156         }                                         
157         if (err)                                  
158                 goto out;                         
159                                                   
160         if (rw_lock)                              
161                 down_read(rw_lock);               
162         err = ntfs_read_bh(sbi, run, vbo, &rec    
163         if (rw_lock)                              
164                 up_read(rw_lock);                 
165                                                   
166         if (err == -E_NTFS_FIXUP) {               
167                 mi->dirty = true;                 
168                 goto ok;                          
169         }                                         
170         if (err)                                  
171                 goto out;                         
172                                                   
173 ok:                                               
174         /* Check field 'total' only here. */      
175         if (le32_to_cpu(rec->total) != bpr) {     
176                 err = -EINVAL;                    
177                 goto out;                         
178         }                                         
179                                                   
180         return 0;                                 
181                                                   
182 out:                                              
183         if (err == -E_NTFS_CORRUPT) {             
184                 ntfs_err(sbi->sb, "mft corrupt    
185                 ntfs_set_state(sbi, NTFS_DIRTY    
186                 err = -EINVAL;                    
187         }                                         
188                                                   
189         return err;                               
190 }                                                 
191                                                   
192 /*                                                
193  * mi_enum_attr - start/continue attributes en    
194  *                                                
195  * NOTE: mi->mrec - memory of size sbi->record    
196  * here we sure that mi->mrec->total == sbi->r    
197  */                                               
198 struct ATTRIB *mi_enum_attr(struct mft_inode *    
199 {                                                 
200         const struct MFT_REC *rec = mi->mrec;     
201         u32 used = le32_to_cpu(rec->used);        
202         u32 t32, off, asize, prev_type;           
203         u16 t16;                                  
204         u64 data_size, alloc_size, tot_size;      
205                                                   
206         if (!attr) {                              
207                 u32 total = le32_to_cpu(rec->t    
208                                                   
209                 off = le16_to_cpu(rec->attr_of    
210                                                   
211                 if (used > total)                 
212                         return NULL;              
213                                                   
214                 if (off >= used || off < MFTRE    
215                     !IS_ALIGNED(off, 4)) {        
216                         return NULL;              
217                 }                                 
218                                                   
219                 /* Skip non-resident records.     
220                 if (!is_rec_inuse(rec))           
221                         return NULL;              
222                                                   
223                 prev_type = 0;                    
224                 attr = Add2Ptr(rec, off);         
225         } else {                                  
226                 /*                                
227                  * We don't need to check prev    
228                  * a bounds checking in the pr    
229                  */                               
230                 off = PtrOffset(rec, attr);       
231                                                   
232                 asize = le32_to_cpu(attr->size    
233                                                   
234                 prev_type = le32_to_cpu(attr->    
235                 attr = Add2Ptr(attr, asize);      
236                 off += asize;                     
237         }                                         
238                                                   
239         /* Can we use the first field (attr->t    
240         /* NOTE: this code also checks attr->s    
241         if (off + 8 > used) {                     
242                 static_assert(ALIGN(sizeof(enu    
243                 return NULL;                      
244         }                                         
245                                                   
246         if (attr->type == ATTR_END) {             
247                 /* End of enumeration. */         
248                 return NULL;                      
249         }                                         
250                                                   
251         /* 0x100 is last known attribute for n    
252         t32 = le32_to_cpu(attr->type);            
253         if (!t32 || (t32 & 0xf) || (t32 > 0x10    
254                 return NULL;                      
255                                                   
256         /* attributes in record must be ordere    
257         if (t32 < prev_type)                      
258                 return NULL;                      
259                                                   
260         asize = le32_to_cpu(attr->size);          
261                                                   
262         /* Check overflow and boundary. */        
263         if (off + asize < off || off + asize >    
264                 return NULL;                      
265                                                   
266         /* Check size of attribute. */            
267         if (!attr->non_res) {                     
268                 /* Check resident fields. */      
269                 if (asize < SIZEOF_RESIDENT)      
270                         return NULL;              
271                                                   
272                 t16 = le16_to_cpu(attr->res.da    
273                 if (t16 > asize)                  
274                         return NULL;              
275                                                   
276                 if (le32_to_cpu(attr->res.data    
277                         return NULL;              
278                                                   
279                 t32 = sizeof(short) * attr->na    
280                 if (t32 && le16_to_cpu(attr->n    
281                         return NULL;              
282                                                   
283                 return attr;                      
284         }                                         
285                                                   
286         /* Check nonresident fields. */           
287         if (attr->non_res != 1)                   
288                 return NULL;                      
289                                                   
290         /* Can we use memory including attr->n    
291         if (asize < SIZEOF_NONRESIDENT)           
292                 return NULL;                      
293                                                   
294         t16 = le16_to_cpu(attr->nres.run_off);    
295         if (t16 > asize)                          
296                 return NULL;                      
297                                                   
298         t32 = sizeof(short) * attr->name_len;     
299         if (t32 && le16_to_cpu(attr->name_off)    
300                 return NULL;                      
301                                                   
302         /* Check start/end vcn. */                
303         if (le64_to_cpu(attr->nres.svcn) > le6    
304                 return NULL;                      
305                                                   
306         data_size = le64_to_cpu(attr->nres.dat    
307         if (le64_to_cpu(attr->nres.valid_size)    
308                 return NULL;                      
309                                                   
310         alloc_size = le64_to_cpu(attr->nres.al    
311         if (data_size > alloc_size)               
312                 return NULL;                      
313                                                   
314         t32 = mi->sbi->cluster_mask;              
315         if (alloc_size & t32)                     
316                 return NULL;                      
317                                                   
318         if (!attr->nres.svcn && is_attr_ext(at    
319                 /* First segment of sparse/com    
320                 /* Can we use memory including    
321                 if (asize < SIZEOF_NONRESIDENT    
322                         return NULL;              
323                                                   
324                 tot_size = le64_to_cpu(attr->n    
325                 if (tot_size & t32)               
326                         return NULL;              
327                                                   
328                 if (tot_size > alloc_size)        
329                         return NULL;              
330         } else {                                  
331                 if (attr->nres.c_unit)            
332                         return NULL;              
333                                                   
334                 if (alloc_size > mi->sbi->volu    
335                         return NULL;              
336         }                                         
337                                                   
338         return attr;                              
339 }                                                 
340                                                   
341 /*                                                
342  * mi_find_attr - Find the attribute by type a    
343  */                                               
344 struct ATTRIB *mi_find_attr(struct mft_inode *    
345                             enum ATTR_TYPE typ    
346                             u8 name_len, const    
347 {                                                 
348         u32 type_in = le32_to_cpu(type);          
349         u32 atype;                                
350                                                   
351 next_attr:                                        
352         attr = mi_enum_attr(mi, attr);            
353         if (!attr)                                
354                 return NULL;                      
355                                                   
356         atype = le32_to_cpu(attr->type);          
357         if (atype > type_in)                      
358                 return NULL;                      
359                                                   
360         if (atype < type_in)                      
361                 goto next_attr;                   
362                                                   
363         if (attr->name_len != name_len)           
364                 goto next_attr;                   
365                                                   
366         if (name_len && memcmp(attr_name(attr)    
367                 goto next_attr;                   
368                                                   
369         if (id && *id != attr->id)                
370                 goto next_attr;                   
371                                                   
372         return attr;                              
373 }                                                 
374                                                   
375 int mi_write(struct mft_inode *mi, int wait)      
376 {                                                 
377         struct MFT_REC *rec;                      
378         int err;                                  
379         struct ntfs_sb_info *sbi;                 
380                                                   
381         if (!mi->dirty)                           
382                 return 0;                         
383                                                   
384         sbi = mi->sbi;                            
385         rec = mi->mrec;                           
386                                                   
387         err = ntfs_write_bh(sbi, &rec->rhdr, &    
388         if (err)                                  
389                 return err;                       
390                                                   
391         if (mi->rno < sbi->mft.recs_mirr)         
392                 sbi->flags |= NTFS_FLAGS_MFTMI    
393                                                   
394         mi->dirty = false;                        
395                                                   
396         return 0;                                 
397 }                                                 
398                                                   
399 int mi_format_new(struct mft_inode *mi, struct    
400                   __le16 flags, bool is_mft)      
401 {                                                 
402         int err;                                  
403         u16 seq = 1;                              
404         struct MFT_REC *rec;                      
405         u64 vbo = (u64)rno << sbi->record_bits    
406                                                   
407         err = mi_init(mi, sbi, rno);              
408         if (err)                                  
409                 return err;                       
410                                                   
411         rec = mi->mrec;                           
412                                                   
413         if (rno == MFT_REC_MFT) {                 
414                 ;                                 
415         } else if (rno < MFT_REC_FREE) {          
416                 seq = rno;                        
417         } else if (rno >= sbi->mft.used) {        
418                 ;                                 
419         } else if (mi_read(mi, is_mft)) {         
420                 ;                                 
421         } else if (rec->rhdr.sign == NTFS_FILE    
422                 /* Record is reused. Update it    
423                 seq = le16_to_cpu(rec->seq) +     
424                 if (!seq)                         
425                         seq = 1;                  
426         }                                         
427                                                   
428         memcpy(rec, sbi->new_rec, sbi->record_    
429                                                   
430         rec->seq = cpu_to_le16(seq);              
431         rec->flags = RECORD_FLAG_IN_USE | flag    
432         if (MFTRECORD_FIXUP_OFFSET == MFTRECOR    
433                 rec->mft_record = cpu_to_le32(    
434                                                   
435         mi->dirty = true;                         
436                                                   
437         if (!mi->nb.nbufs) {                      
438                 struct ntfs_inode *ni = sbi->m    
439                 bool lock = false;                
440                                                   
441                 if (is_mounted(sbi) && !is_mft    
442                         down_read(&ni->file.ru    
443                         lock = true;              
444                 }                                 
445                                                   
446                 err = ntfs_get_bh(sbi, &ni->fi    
447                                   &mi->nb);       
448                 if (lock)                         
449                         up_read(&ni->file.run_    
450         }                                         
451                                                   
452         return err;                               
453 }                                                 
454                                                   
455 /*                                                
456  * mi_insert_attr - Reserve space for new attr    
457  *                                                
458  * Return: Not full constructed attribute or N    
459  */                                               
460 struct ATTRIB *mi_insert_attr(struct mft_inode    
461                               const __le16 *na    
462                               u16 name_off)       
463 {                                                 
464         size_t tail;                              
465         struct ATTRIB *attr;                      
466         __le16 id;                                
467         struct MFT_REC *rec = mi->mrec;           
468         struct ntfs_sb_info *sbi = mi->sbi;       
469         u32 used = le32_to_cpu(rec->used);        
470         const u16 *upcase = sbi->upcase;          
471                                                   
472         /* Can we insert mi attribute? */         
473         if (used + asize > sbi->record_size)      
474                 return NULL;                      
475                                                   
476         /*                                        
477          * Scan through the list of attributes    
478          * at which we should insert it.          
479          */                                       
480         attr = NULL;                              
481         while ((attr = mi_enum_attr(mi, attr))    
482                 int diff = compare_attr(attr,     
483                                                   
484                 if (diff < 0)                     
485                         continue;                 
486                                                   
487                 if (!diff && !is_attr_indexed(    
488                         return NULL;              
489                 break;                            
490         }                                         
491                                                   
492         if (!attr) {                              
493                 /* Append. */                     
494                 tail = 8;                         
495                 attr = Add2Ptr(rec, used - 8);    
496         } else {                                  
497                 /* Insert before 'attr'. */       
498                 tail = used - PtrOffset(rec, a    
499         }                                         
500                                                   
501         id = mi_new_attt_id(mi);                  
502                                                   
503         memmove(Add2Ptr(attr, asize), attr, ta    
504         memset(attr, 0, asize);                   
505                                                   
506         attr->type = type;                        
507         attr->size = cpu_to_le32(asize);          
508         attr->name_len = name_len;                
509         attr->name_off = cpu_to_le16(name_off)    
510         attr->id = id;                            
511                                                   
512         memmove(Add2Ptr(attr, name_off), name,    
513         rec->used = cpu_to_le32(used + asize);    
514                                                   
515         mi->dirty = true;                         
516                                                   
517         return attr;                              
518 }                                                 
519                                                   
520 /*                                                
521  * mi_remove_attr - Remove the attribute from     
522  *                                                
523  * NOTE: The source attr will point to next at    
524  */                                               
525 bool mi_remove_attr(struct ntfs_inode *ni, str    
526                     struct ATTRIB *attr)          
527 {                                                 
528         struct MFT_REC *rec = mi->mrec;           
529         u32 aoff = PtrOffset(rec, attr);          
530         u32 used = le32_to_cpu(rec->used);        
531         u32 asize = le32_to_cpu(attr->size);      
532                                                   
533         if (aoff + asize > used)                  
534                 return false;                     
535                                                   
536         if (ni && is_attr_indexed(attr) && att    
537                 u16 links = le16_to_cpu(ni->mi    
538                 if (!links) {                     
539                         /* minor error. Not cr    
540                 } else {                          
541                         ni->mi.mrec->hard_link    
542                         ni->mi.dirty = true;      
543                 }                                 
544         }                                         
545                                                   
546         used -= asize;                            
547         memmove(attr, Add2Ptr(attr, asize), us    
548         rec->used = cpu_to_le32(used);            
549         mi->dirty = true;                         
550                                                   
551         return true;                              
552 }                                                 
553                                                   
554 /* bytes = "new attribute size" - "old attribu    
555 bool mi_resize_attr(struct mft_inode *mi, stru    
556 {                                                 
557         struct MFT_REC *rec = mi->mrec;           
558         u32 aoff = PtrOffset(rec, attr);          
559         u32 total, used = le32_to_cpu(rec->use    
560         u32 nsize, asize = le32_to_cpu(attr->s    
561         u32 rsize = le32_to_cpu(attr->res.data    
562         int tail = (int)(used - aoff - asize);    
563         int dsize;                                
564         char *next;                               
565                                                   
566         if (tail < 0 || aoff >= used)             
567                 return false;                     
568                                                   
569         if (!bytes)                               
570                 return true;                      
571                                                   
572         total = le32_to_cpu(rec->total);          
573         next = Add2Ptr(attr, asize);              
574                                                   
575         if (bytes > 0) {                          
576                 dsize = ALIGN(bytes, 8);          
577                 if (used + dsize > total)         
578                         return false;             
579                 nsize = asize + dsize;            
580                 /* Move tail */                   
581                 memmove(next + dsize, next, ta    
582                 memset(next, 0, dsize);           
583                 used += dsize;                    
584                 rsize += dsize;                   
585         } else {                                  
586                 dsize = ALIGN(-bytes, 8);         
587                 if (dsize > asize)                
588                         return false;             
589                 nsize = asize - dsize;            
590                 memmove(next - dsize, next, ta    
591                 used -= dsize;                    
592                 rsize -= dsize;                   
593         }                                         
594                                                   
595         rec->used = cpu_to_le32(used);            
596         attr->size = cpu_to_le32(nsize);          
597         if (!attr->non_res)                       
598                 attr->res.data_size = cpu_to_l    
599         mi->dirty = true;                         
600                                                   
601         return true;                              
602 }                                                 
603                                                   
604 /*                                                
605  * Pack runs in MFT record.                       
606  * If failed record is not changed.               
607  */                                               
608 int mi_pack_runs(struct mft_inode *mi, struct     
609                  struct runs_tree *run, CLST l    
610 {                                                 
611         int err = 0;                              
612         struct ntfs_sb_info *sbi = mi->sbi;       
613         u32 new_run_size;                         
614         CLST plen;                                
615         struct MFT_REC *rec = mi->mrec;           
616         CLST svcn = le64_to_cpu(attr->nres.svc    
617         u32 used = le32_to_cpu(rec->used);        
618         u32 aoff = PtrOffset(rec, attr);          
619         u32 asize = le32_to_cpu(attr->size);      
620         char *next = Add2Ptr(attr, asize);        
621         u16 run_off = le16_to_cpu(attr->nres.r    
622         u32 run_size = asize - run_off;           
623         u32 tail = used - aoff - asize;           
624         u32 dsize = sbi->record_size - used;      
625                                                   
626         /* Make a maximum gap in current recor    
627         memmove(next + dsize, next, tail);        
628                                                   
629         /* Pack as much as possible. */           
630         err = run_pack(run, svcn, len, Add2Ptr    
631                        &plen);                    
632         if (err < 0) {                            
633                 memmove(next, next + dsize, ta    
634                 return err;                       
635         }                                         
636                                                   
637         new_run_size = ALIGN(err, 8);             
638                                                   
639         memmove(next + new_run_size - run_size    
640                                                   
641         attr->size = cpu_to_le32(asize + new_r    
642         attr->nres.evcn = cpu_to_le64(svcn + p    
643         rec->used = cpu_to_le32(used + new_run    
644         mi->dirty = true;                         
645                                                   
646         return 0;                                 
647 }                                                 
648                                                   

~ [ 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