Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm trying to create a linux kernel module that allows for key value store functionality to be used by other programs in user space. I'm not sure how to go about interacting with the two.
My thought is to use hashtables and make something basic for now, like this:
struct hashtable{
char name[100];
int data;
struct hlist_node my_hash_list;
}
static int hash_table_init(void){
//TODO
return 0;
}
module_init(hash_table_init);
More specifically; with a basic module like this, how would I perform operations such as adding to the hashtable from user space? I understand file operations are one way to communicate to and from the module, but I'm not sure how that would work in this case, if applicable.
I think the most common paradigm used is VFS based operations on either sysfs or devfs. Using struct file_operations you can define a vtable for handling userspace operating on your virtual file. This is explained in much greater detail here.
In your specific case, a miscdevice would be the best approach with IOCTLs defined to add, get or remove entries from your hashtable. A great example of a basic miscdevice driver can be found here. Your IOCTL could take a userspace address use copy_from_user to get the necessary buffer pointed to by data in the IOCTL invocation (like the name of the key or the hash) and similary a IOCTL to get something by using copy_to_user to copy the contents of a specific key to userspace. (similar to BSD's copyin/copyout).
Netlink sockets are another way of user<->kernel communication, you can find an example here. They're slightly more complicated to use, I would not suggest them if you're just starting out with kernel development.
If you want to mess with arch/ code you could also add your own system call that would call into your driver, that requires that a certain part of your driver is always present in the kernel, at least to check if the driver is loaded and forward the call. If you're going that way you cannot compile the whole driver as a module and you should generally not try to do the split approach I just described and make sure it's only compilable as part of the kernel.
Now onto the scary part, you really are playing with fire here, in the kernel you have to be extremely vigilant in terms of boundary checks, locking, preemption awareness (ie. don't yield under a spinlock), resource management and address checks since you will crash the system or even worse introduce a security vulnerability should something go wrong.
I would not suggest trying this, unless this is just for learning how to do kernel development. Even a basic driver like the ones in the example can easily introduce critical security bugs or instability into the kernel.
If this is not just for learning then may I suggest memcached or Redis both of which are userspace and have been battle-tested and are in use by many companies as out-of-process shared hashtables, with or without network transparency (ie. Redis can work over a UNIX domain socket).
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I have a data file that needs to be pushed to an embedded device. The typical size for the file ranges from a few bytes to about 10K max. My intention is to detect tampering with the contents of this file(chksum to be last element in the data file). The data range is a mix of strings, signed and unsigned integers. I am looking for a robust algo to avoid a lot of collisions as well something that does not use a lot of cycles to compute. I am considering Fletcher16(), CRC-32 and the solution discussed in this post
Any suggestions for a simple algo for my kind of data size/contents?
Thanks in advance!
EDIT:-
Thanks everyone for the insightful answers and suggestions.
Some background: This is not a hyper secure data file. I just want to be able to detect whether someone wrote it by mistake. The file gets generated by a module and should be just read only by the SW. Recently there has been a few instances where folks have pulled it from the target file system, edited and pushed back to the target hoping that would fix their problems. (Which btw it would if edited carefully). But this defeats the very purpose of auto generatating this file and the existence of this module. I would like to detect and such playful "hacks" and abort gracefully.
My intention is to detect tampering with the contents of this file
If you need to detect intentional tampering with a file, you need some sort of cryptographic signature -- not just a hash.
If you can protect a key within the device, using HMAC as a signature algorithm may be sufficient. However, if the secret is extracted from the device, users will be able to use this to forge signatures.
If you cannot protect a key within the device, you will need to use an asymmetric signature algorithm. Libsodium's crypto_sign APIs provide a nice API for this. Alternatively, if you want to use the underlying algorithms directly, EdDSA is a decent choice.
Either of these options will require a relatively large amount of space (32 to 64 bytes) to be allocated for a signature, and verifying that signature will take significantly more time than a noncryptographic signature. This is largely unavoidable if you need to effectively prevent tampering.
For your purpose, you can use a cryptographic hash such as SHA256. It is very reliable and collisions are abysmally unlikely but you should test if the speed is OK.
There is a sample implementation in this response: https://stackoverflow.com/a/55033209/4593267
To detect intentional tampering with the data, you can add a secret key to the hashed data. The device will need to have a copy of the secret key, so it is not a very secure method as the key could be extracted from the device through reverse engineering or other methods. If the device is well protected against that, for example if it is inside a secure location, a secure chip or in a very remote location such as a satellite in space and you are confident there are no flaws providing remote access, this may be sufficient.
Otherwise an asymmetrical cryptographic system is required, with a private key known only to the legitimate source(s) of those data files, and a public key used by the device to verify the cryptographic hash, as documented in duskwuff's answer.
If you're only concerned about accidental or non-malicious tampering, a CRC should be sufficient.
(I'm using a somewhat circular definition of 'malicious' here: if somebody goes to the trouble of recalculating or manipulating the CRC to get their edits to work, that counts as 'malicious' and we don't defend against it.)
It have often noticed that I would have been able to solve practical problems in C elegantly if there had been a way of creating a ‘virtual FILE’ and attaching the necessary callbacks for events such as buffer full, input requested, close, flush. It should then be possible to use a large part of the stdio.h functions, e.g. fprintf unchanged. Is there a framework enabling one to do this? If not, is it feasible with a moderate amount of effort, on at least some platforms?
Possible applications would be:
To write to or read from a dynamic or static region of memory.
To write to multiple files in parallel.
To read from a thread or co-routine generating data.
To apply a filter to another (virtual or real) FILE.
Support for file formats with indirection (like #include).
A C pre-processor(?).
I am less interested in solutions for specific cases than in a framework to let you roll your own FILE. I am also not looking for a virtual filesystem, but rather virtual FILE*s that I can pass to the CRT.
To my disappointment I have never seen anything of the sort; as far as I can see C11 considers FILE entirely up to the language implementer, which is perhaps reasonable if one wishes to keep the language (+library) specifications small but sad if you compare it with Java I/O streams.
I feel sure that virtual FILEs must be possible with any (fully) open source implementation of the C run-time, but I imagine there might be a large number of details making it trickier than it seems, and if it has already been done it would be a shame to reduplicate the effort. It would also be greatly preferable not to have to modify the CRT code. Without open source one might be able to reverse engineer the functions supplied, but I fear the result would be far too vulnerable to changes in unsupported features, unless there were a commitment to a set of interfaces. I suppose too that any system for which one can write a device driver would allow one to create a virtual device, but I suspect that of being unnecessarily low-level and of requiring one to write privileged code.
I have to admit that while I have code that would have benefited from virtual FILEs, I have no current requirement for it; nonetheless it is something I have often wondered about and that I imagine could be of interest to others.
This is somewhat similar to a-reader-interface-that-consumes-files-and-char-in-c, but there the questioner did not hope to return a virtual FILE; the answer, however, using fmemopen, did.
There is no standard C interface for creating virtual FILE*s, but both the GNU and the BSD standard libraries include one. On linux (glibc), you can use fopencookie; on most *BSD systems, funopen (including Mac OS X). (See Note 1)
The two interfaces are similar but slightly different in some details. However, it is usually very simple to adapt code written for one interface to the other.
These are not complete virtualizations. They associated the FILE* with four callbacks and a void* context (the "cookie" in fopencookie). The callbacks are read, write, seek and close; there are no callbacks for flush or tell operations. Still, this is sufficient for many simple FILE* adaptors.
For a simple example, see the two answers to Write simultaneousely to two streams.
Notes:
funopen is derived from "functional open", not from "file unopen".
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I am trying to use my webcam (Creative Live! Cam Chat) to take an image in C/C++ and save it to a certain folder(running Ubuntu). Ideally I'm looking to something as simple as possible despite it not being the most elegant solution.
So far I've found v4l2grab which I find incredibly confusing to understand, and also doesn't seem to work with the Creative webcam (returns a black picture that is 5Kb in size) although it does seem to work with the webcam installed as a part of my laptop.
Are there any simple C libraries or code that I could use to do this?
I don't know of a good library for the purpose (please add comment and tell me if there is one :-)). Note: for some uses, eg. OpenCV is just fine, and if it is enough for you, definitely do use it. But if you want more, read on.
So you should just write your own code to use it, it's not particularly hard. Here's one related question: How to use/learn Video4Linux2 (On Screen Display) Output APIs?
Some points to make learning easier:
After calling an IOCTL, always check return status and print possible error message. You will be getting lots of these while you work, so just be systematic about it. I suggest a function like check_error shown below, and calling it always immediatly after any ioctl call.
IMO a must: use IDE/editor, which can follow symbol to the actual header file (for example in Qt Creator, which is a fine pure C application IDE despite the name, hit F2 on symbol, and it will go even to system headers to show you where it is defined). Use this liberally on V4L2 related symbols and defines, and read comments in the header file, that's often the best documentation.
Use the query ioctls and write functions to dump values they return in nice format. For example have function void dump_cap(const struct v4l2_capability &cap) {...}, and add a similar function for every struct you use in your code as you go.
Don't be lazy about setting values inside structs you pass to IOCTL. Always initialize structs to 0 with memset(&ioctl_struct_var, 0, sizeof(ioctl_struct_var)); after declaring them, and also if you reuse them (except when doing 'get-modify-set' operation on some settings, which is quite common with V4L2).
If possible, have two (or more) different webcams (different resolutions, different brand), and test with both (all). This is easiest if you take video device as command line parameter, so you can just call your program with different argument for each cam you have.
Small steps. Often ioctls may not return what you expect, so no point writing code which uses the returned data, before you have actually seen what the query returns for your cameras.
The check_error function mentioned above:
void check_error(int return_value_of_ioctl, const char *msg) {
if (return_value_of_ioctl != -1) return; /* all ok */
int eno = errno; /* just to avoid accidental clobbering of errno */
fprintf(stderr, "error (%d) with %s: %s\n", eno, msg, strerror(eno));
exit(1); /* optional, depending on how you want to work with your code */
}
Call that immediatly after every ioctl, for example:
struct v4l2_capability cap;
setmem(&cap, 0, sizeof(cap));
int r=ioctl(fd, VIDIOC_QUERYCAP, &cap);
check_error(r, "VIDIOC_QUERYCAP");
dump_querycap(&cap);
You can use OpenCV. Use cvCreatecameraCapture (You can call it with argument 0 to get to the fault cam) to create an object and then call cvQueryFrame on that object. Calling cvQueryFrame each time will return a frame.
Have you had a look at OpenCV? It's quite handy for all sorts of image getting and processing. The process of taking picture is well documented, but I suggest you look at something like this, if you do indeed decide to use it.
Take a look at uvccapture source code. It is very simple, yet standard C which uses only V4L2 interface. OpenCV would also work, but it is more complicated to setup and compile.
I am attempting to modify the bio structure (in blk_types.h) for linux-3.2.0 (running Ubuntu). The only thing I need to do to this structure is to add an additional variable to keep track of an integer variable (it is for a tainting algorithm). However, adding a single line such as "int id;" to the structure halts the boot sequence of the OS.
It compiles, but when booting it gives the following error:
>Gave up wiating for root device. Common problems:
>Boot args
>check rootdelay= ...
>check root= ...
>missing modules (cat /proc/modules; ls /dev)
>ALERT! /dev/disk/by-uuid/15448888-84a0-4ccf-a02a-0feb3f150a84 does not exist. Dropping to a shell!
>BusyBox Built In Shell ...
>(initramfs)
I took a look around using the given shell and could not find the desired file system by uuid or otherwise (no /dev/sda). Any ideas what might be going on?
Thanks,
-Misiu
I suppose you are trying to modify the Linux kernel header bio.h, not its userland "friend" bui.h.
Said that I must warn you that in many places around kernel sizeof() may be used which is more portable and perhaps some other implementation or API may expect some fixed size. If the later is true then you'll have problems since bio' struct size has been changed by you.
It is a guessing with no further investigation from my side (I mean I hadn't investigate about bio in detail) but when patching the Linux kernel one must make sure of any possible side effects and take the whole scenario on account, specially when modifying lower levels implementation.
Bio helper functions do lots of low level operations on bio struct, take a loot at bio_integrity.c for example.
I managed to fix the problem with your help Caf. Though re-building/installing the modules did not seem to help immediately, I was able to get the system to boot by building the SATA drivers into the kernel, as advised by this forum thread: https://unix.stackexchange.com/questions/8405/kernel-cant-find-dev-sda-file-during-boot.
Thanks for your help,
-Misiu
I'm learning about the registration of a kernel module using register_chrdev_region(dev_t from, unsigned count, const char * name);.
I notice that with or without this function, my kernel module worked as expected. The code I used for testing:
first = MKDEV(MAJOR_NUM, MINOR_NUM);
register_chrdev_region(first, count, DEVICE_NAME);//<---with and without
mycdev=cdev_alloc();
mycdev->ops= &fops;
mycdev->owner = THIS_MODULE;
if (cdev_add(mycdev,first, count) == 0)
{printk(KERN_ALERT "driver loaded\n");}
I commented out the line register_chrdev_region(first, count, DEVICE_NAME);, and the printk message still appeared. I tried to communicate with the driver with or without this from user space, and both are successful.
So my question is, is this function register_chrdev_region() only used to make my driver a good kernel citizen, just like telling the others that "I'm using up the major number, please don't use"?
I tried to have a look in the kernel source char_dev.c to understand the function, but I find it too difficult to understand, anyone that's familiar with this?
Thanks!
That will work because it's not actually necessary to allocate your device numbers up front. In fact, it's considered preferable by many kernel developers to use the dynamic (on-the-fly, as-needed) allocation function alloc_chrdev_region.
Whether you do it statically up front or dynamically as needed, it is something you should do to avoid conflict with other device drivers which may have played by the rules and been allocated the numbers you're trying to use. Even if your driver works perfectly well without it, that won't necessarily be true on every machine or at any time in the future.
The rules are there for a reason and, especially with low-level stuff, you are well advised to follow them.
See here for more details on the set-up process.
If the major number for your devices clash with any other device already in use, then the driver won't have the allocation done.
If you have already tested which major number is free and used it, it might generally not throw up an error and you will face no problem as u load the driver.
But if you run on various systems and if the major number is already captured and used by some other system., Then your driver loading can fail.
Its always better to use dynamic allocation !!