1.\" $NetBSD: fileassoc.9,v 1.9 2006/09/06 13:37:49 blymn Exp $ 2.\" 3.\" Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 3. All advertising materials mentioning features or use of this software 15.\" must display the following acknowledgement: 16.\" This product includes software developed by Elad Efrat. 17.\" 4. The name of the author may not be used to endorse or promote products 18.\" derived from this software without specific prior written permission. 19.\" 20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30.\" 31.Dd September 4, 2006 32.Dt FILEASSOC 9 33.Os 34.Sh NAME 35.Nm fileassoc 36.Nd in-kernel, file-system independent, file-meta data association 37.Sh SYNOPSIS 38.In sys/fileassoc.h 39.Sh DESCRIPTION 40The 41.Nm 42KPI allows association of meta-data with files independent of file-system 43support for such elaborate meta-data. 44.Pp 45A system can have a maximum number of 46.Dv FILEASSOC_NHOOKS 47fileassocs associated with each file. 48.Pp 49When plugging a new fileassoc to the system, a developer can specify private 50data to be associated with every file, as well as (potentially different) 51private data to be associated with every file-system mount. 52.Pp 53For example, a developer might choose to associate a custom ACL with every 54file, and a count of total files with ACLs with the mount. 55.Ss Kernel Programming Interface 56Designed with simplicity in mind, the 57.Nm 58KPI usually accepts four different types of parameters to the most commonly 59used routines: 60.Bl -tag -width "123456" 61.It Ft struct mount * Ar mp 62Describing a mount on which to take action. 63.It Ft struct vnode * Ar vp 64Describing a file on which to take action. 65.It Ft fileassoc_t Ar id 66Describing an id, as returned from a successful call to 67.Fn fileassoc_register . 68.It Ft void * Ar data 69Describing a custom private data block, attached to either a file or a mount. 70.El 71.Pp 72Before using the 73.Nm 74KPI it is important to keep in mind that the interface provides memory 75management only for 76.Nm 77internal memory. 78Any additional memory stored in the tables (such as private data-structures 79used by custom fileassocs) should be allocated and freed by the developer. 80.Pp 81.Nm 82provides the ability to specify a 83.Dq cleanup 84routine to 85.Fn fileassoc_register 86(see below) 87to be called whenever an entry for a file or a mount is deleted. 88.Ss Fileassoc Registration and Deregistration Routines 89These routines allow a developer to allocate a 90.Nm 91slot to be used for private data. 92.Bl -tag -width "123456" 93.It Ft int Fn fileassoc_register "const char *name" "fileassoc_cleanup_cb cleanup_cb" 94Registers a new fileassoc as 95.Ar name , 96and returns an 97.Ft int 98to be used as a metahhook-id in subsequent calls to the 99.Nm 100subsystem to identify the fileassoc, or \-1 on failure. 101.Pp 102If 103.Ar cleanup_cb 104is not 105.Dv NULL , 106it will be called during delete/clear operations (see routines below) with 107indication whether the passed data is file- or mount-specific. 108.Pp 109.Ar cleanup_cb 110should be a function receiving a 111.Ft void * 112and an 113.Ft int , 114returning 115.Ft void . 116See the 117.Sx EXAMPLES 118section for illustration. 119.Pp 120.It Ft int Fn fileassoc_deregister "fileassoc_t id" 121Deregisters a 122.Nm fileassoc 123whose id is 124.Ar id . 125.Pp 126Note that calling 127.Fn fileassoc_deregister 128only frees the associated slot in the 129.Nm 130subsystem. 131It is up to the developer to take care of garbage collection. 132.El 133.Ss Lookup Routines 134These routines allow lookup of 135.Nm 136mounts, files, and private data attached to them. 137.Bl -tag -width "123456" 138.It Ft void * Fn fileassoc_tabledata_lookup "struct mount *mp" "fileassoc_t id" 139Return table-wide private data in 140.Ar mp 141for 142.Ar id . 143.Pp 144.It Ft void * Fn fileassoc_lookup "struct vnode *vp" "fileassoc_t id" 145Returns the private data for the file/id combination 146or 147.Dv NULL 148if not found. 149.El 150.Ss Mount-wide Routines 151.Bl -tag -width "123456" 152.It Ft int Fn fileassoc_table_add "struct mount *mp" "size_t size" 153Creates a new fileassoc table for 154.Ar mp 155with at least 156.Ar size 157slots. 158.Pp 159.It Ft int Fn fileassoc_table_delete "struct mount *mp" 160Deletes a fileassoc table for 161.Ar mp . 162.Pp 163If specified, the fileassoc's 164.Dq cleanup routine 165will be called with a pointer to the private data-structure and indication of 166.Dv FILEASSOC_CLEANUP_TABLE . 167.Pp 168.It Ft int Fn fileassoc_table_clear "struct mount *mp" "fileassoc_t id" 169Clear all table entries for 170.Ar fileassoc 171from 172.Ar mp . 173.Pp 174If specified, the fileassoc's 175.Dq cleanup routine 176will be called with a pointer to the private data-structure and indication of 177either 178.Dv FILEASSOC_CLEANUP_FILE 179or 180.Dv FILEASSOC_CLEANUP_TABLE 181as appropriate. 182.Pp 183.It Ft int Fn fileassoc_tabledata_add "struct mount *mp" "fileassoc_t id" "void *data" 184Add table-wide fileassoc-specific data in 185.Ar data 186to 187.Ar mp 188for 189.Ar id . 190.Pp 191.It Ft int Fn fileassoc_tabledata_clear "struct mount *mp" "fileassoc_t id" 192Clear table-wide fileassoc-specific data in 193.Ar mp 194for 195.Ar id . 196.It Ft int Fn fileassoc_table_run "struct mount *mp" "fileassoc_t id" \ 197"fileassoc_cb_t cb" 198For each entry for 199.Ar id , 200call 201.Ar cb 202with the entry being the argument. 203.Pp 204.Ar cb 205is a function returning 206.Ft void 207and receiving one 208.Ft "void *" 209parameter. 210.El 211.Ss File-specific Routines 212.Bl -tag -width "123456" 213.It Ft int Fn fileassoc_file_delete "struct vnode *vp" 214Delete the fileassoc entry for 215.Ar vp . 216.Pp 217If specified, the fileassoc's 218.Dq cleanup routine 219will be called with a pointer to the private data-structure and indication of 220.Dv FILEASSOC_CLEANUP_FILE . 221.El 222.Ss Fileassoc-specific Routines 223.Bl -tag -width "123456" 224.It Ft int Fn fileassoc_add "struct vnode *vp" "fileassoc_t id" "void *data" 225Add private data in 226.Ar data 227for 228.Ar vp , 229for the fileassoc specified by 230.Ar id . 231.Pp 232.It Ft int Fn fileassoc_clear "struct vnode *vp" "fileassoc_t id" 233Clear the private data for 234.Ar vp , 235for the fileassoc specified by 236.Ar id . 237.Pp 238If specified, the fileassoc's 239.Dq cleanup routine 240will be called with a pointer to the private data-structure and indication of 241.Dv FILEASSOC_CLEANUP_FILE . 242.El 243.Ss Misc. Routines 244.Bl -tag -width "123456" 245.It Ft void Fn fileassoc_init "void" 246Initializes the 247.Nm 248subsystem. 249.Fn fileassoc_init 250is called once during system boot. 251.El 252.Sh EXAMPLES 253The following code examples should give you a clue on using 254.Nm 255for your purposes. 256.Pp 257First, we'll begin with registering a new id. 258We need to do that to save a slot for private data storage with each mount 259and/or file: 260.Bd -literal -offset indent 261fileassoc_t myhook_id; 262 263myhook_id = fileassoc_register("my_hook", myhook_cleanup); 264if (myhook_id == -1) 265 ...handle error... 266.Ed 267.Pp 268In the above example we pass a 269.Fn myhook_cleanup 270routine. 271It could look something like this: 272.Bd -literal -offset indent 273void 274myhook_cleanup(void *data, int what) 275{ 276 if (what == FILEASSOC_CLEANUP_FILE) { 277 printf("Myhook: Removing entry for file.\n"); 278 ...handle file entry removal... 279 free(data, M_TEMP); 280 } else if (what == FILEASSOC_CLEANUP_TABLE) { 281 printf("Myhook: Removing entry for mount.\n"); 282 ...handle mount entry removal... 283 free(data, M_TEMP); 284 } 285} 286.Ed 287.Pp 288Another useful thing would be to add our private data to a file. 289For example, let's assume we keep a custom ACL with each file: 290.Bd -literal -offset indent 291int 292myhook_acl_add(struct vnode *vp, struct myhook_acl *acl) 293{ 294 int error; 295 296 error = fileassoc_add(vp, myhook_id, acl); 297 if (error) { 298 printf("Myhook: Could not add ACL.\n"); 299 ...handle error... 300 } 301 302 printf("Myhook: Added ACL.\n"); 303 304 return (0); 305} 306.Ed 307.Pp 308Adding an entry will override any entry that previously exists. 309.Pp 310The above can fail, usually when there is no table for the mount. 311Creating a new table is simple: 312.Bd -literal -offset indent 313int error; 314 315error = fileassoc_table_add(vp-\*[Gt]v_mount, nentries); 316if (error) 317 ...handle error... 318.Ed 319.Pp 320The second argument to 321.Fn fileassoc_table_add , 322.Ar nentries , 323should be approximately the number of files it is predicted that will 324have entries in the table, although you can provide a pseudo-safe constant 325value (like 128, for example). 326.Pp 327Whatever your plug is, eventually you'll want to access the private data you 328store with each file. 329To do that you can use the following: 330.Bd -literal -offset indent 331int 332myhook_acl_access(struct vnode *vp, int access_flags) 333{ 334 struct myhook_acl *acl; 335 336 acl = fileassoc_lookup(vp, myhook_id); 337 if (acl == NULL) 338 return (0); 339 340 error = myhook_acl_eval(acl, access_flags); 341 if (error) { 342 printf("Myhook: Denying access based on ACL decision.\n"); 343 return (error); 344 } 345 346 return (0); 347} 348.Ed 349.Pp 350And, in some cases, it may be desired to remove private data associated with 351an file: 352.Bd -literal -offset indent 353int error; 354 355error = fileassoc_clear(vp, myhook_id); 356if (error) { 357 printf("Myhook: Error occured during fileassoc removal.\n"); 358 ...handle error... 359} 360.Ed 361.Pp 362As mentioned previously, the call to 363.Fn fileassoc_clear 364will result in a call to the 365.Dq cleanup routine 366specified in the initial call to 367.Fn fileassoc_register . 368.Pp 369The above should be enough to get you started. 370.Pp 371For example usage of 372.Nm , 373see the Veriexec code. 374.Sh CODE REFERENCES 375.Pa src/sys/kern/kern_verifiedexec.c 376.Sh HISTORY 377The 378.Nm 379KPI first appeared in 380.Nx 4.0 . 381.Sh AUTHORS 382.An Elad Efrat Aq elad@NetBSD.org 383.An Brett Lymn Aq blymn@NetBSD.org 384