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.
The community reviewed whether to reopen this question 11 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
Can anyone tell me about this...
I want to create a pam module similar to the login module in /etc/pam.d
If you are looking for pam based face authentication during login, you need to write a module which does that for you and plug that in login configuration file at /etc/pam.d/login.
Before directly get into this, I would suggest you to write some simple module to understand the flow, working of PAM and configuration file like start playing with sshd pam configuration file and try to plug some sample pam module available. I found these article quite helpful :
http://aplawrence.com/Basics/understandingpam.html
https://www.packtpub.com/article/development-with-pluggable-authentication-modules-pam
FYI : Rohan Anil developed pam-face-authentication during GSOC08 under opensuse which is hosted at code.google.com/p/pam-face-authentication/
Since the answer is really to long to be written here, I can link you my PAM tutorials:
Write a Linux PAM module and
Linux PAM Configuration tutorial
Before starting writing the module I advise you to read the configuration tutorial first, in which you can learn what does the module do.
To sum up, a module is a shared object loaded by PAM when the application wants to authenticate. Every time the application triggers a "stage" (auth, account, session, password) the correspondent function is called in the module. Therefore, your module should provide the following functions:
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *handle, int flags, int argc, const char **argv){
/* In this function we will ask the username and the password with pam_get_user()
* and pam_get_authtok(). We will then decide if the user is authenticated */
}
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) {
/* In this function we check that the user is allowed in the system. We already know
* that he's authenticated, but we could apply restrictions based on time of the day,
* resources in the system etc. */
}
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) {
/* We could have many more information of the user other then password and username.
* These are the credentials. For example, a kerberos ticket. Here we establish those
* and make them visible to the application */
}
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) {
/* When the application wants to open a session, this function is called. Here we should
* build the user environment (setting environment variables, mounting directories etc) */
}
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) {
/* Here we destroy the environment we have created above */
}
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv){
/* This function is called to change the authentication token. Here we should,
* for example, change the user password with the new password */
}
In this functions you will use PAM functions to retrieve the username and the password from the application. This happens through a conversation function that must be defined in the application (see this tutorial). At the end of every function, you must return a PAM return code that determines the result (for PAM error codes see this and the module writer documentation in general).
One of the best resources for authoring pam modules is the documentation
itself:
http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_MWG.html
However I agree with #GG in making sure you understand how PAM works first.
Related
The question may seem naive, but I'm new to kernel/driver programming. I created a device mapper over a block device, which is working fine. It's constructor/destructor and map methods are called.
Now, I'm trying to write an ioctl for this mapper. When ioctl is written for a device, it has the following signature:
int ioctl(int d, /* other args */);
A file structure/descriptor is expected in ioctl. This can be easily used by application process as it has access to file.
But the ioctl for device mapper has the following signature ( in struct target_type):
typedef int (*dm_ioctl_fn) (struct dm_target *ti, unsigned int cmd,
unsigned long arg);
How can user application get access to device mapper with ioctl without having knowledge of struct dm_target ?
-Ioctl which stand for Input Output control is a system call used in linux to implement system calls which are not be available in the
kernel by default.
-The major use of this is in case of handling some specific operations of a device for which the kernel does not have a system call by default. For eg: Ejecting the media from a "CD" drive. An ioctl command is implemented to give the eject system call to the cd drive.
-ioctl(fd, cmd , INPARAM or OUTPARAM);
|
3rd argument is INPARAM or OUTPARAM i.e we don't have to read a device, then how how to interact with device ? use ioctl.
-open ioctl.h and check you will get more information
#define "ioctl name" __IOX("magic number","command number","argument type")
static long char_dev_ioctl( struct file *filp, unsigned int cmd, unsigned long arg)
{
/* verify argument using access_ok() */
/* impliment support of ioctl commands */
}
My project contains two things: kernel module & app, that are communicating via ioctl using /dev/mytest file.
Currently, app is required to be run as root to access /dev/mytest file. Is it possible to allow non-users to iteract with this file without sudo?
As i understood, file_operations structure property .owner = THIS_MODULE has nothing about /dev/mytest file and is associated only with driver file.
I create /dev/mytest using class_create & device_create functions in kernel module. So, perhaps i should specify some special device_create parameters? Or how i can achieve it?
In a modern kernel, you can do something like
myclass = class_create(THIS_MODULE, "my_class_name");
/* error handling if class_create fails */
myclass->devnode = mydevnode;
where your devnode function is something like
static char *mydevnode(struct device *dev, umode_t *mode)
{
if (mode)
*mode = 0666; /* or whatever permissions you want */
return NULL; /* could override /dev name here too */
}
then if you use device_create to create your driver special file, the kernel will call mydevnode to create the file, and you can override the file permissions there.
I have to declare multiple devices inside the open call. Now is there a way I could fix the minor nos to 0,1,2,3 so that I can just extract that from filp->f_dentry->inode and put that in the array of struct scull_dev[] everytime I make an open read write or close call and then life becomes easy :P. Or is their a way to make life easier ?
If I understand what you need, you shouldn't have ever to access your devices directly except for initialization and cleanup. Take a look at:
http://www.cs.uni.edu/~diesburg/courses/dd/code/scull/pipe.c
In open function, you can get the current device you need to open via:
struct scull_pipe *dev;
dev = container_of(inode->i_cdev, struct scull_pipe, cdev);
You can see in other functions how the device is accessed via arguments that kernel is passing to these functions. For example:
static ssize_t scull_p_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
struct scull_pipe *dev = filp->private_data;
Basically, I want to have a configuration file, e.g. "myconfigfile" that contains a string of characters, for example "abcdefg".
I want to read this string in as a value in my kernel module. That is, I want to have a char* in my code that gets the value "abcdefg" from that file. From what I understand, I should use sysfs. Here are my questions:
Do I just create the file and move it into /sys/module/path/to/my/module directory ?
If I have the file available, how exactly do I read the value? Say the file is called "myconfigfile". I read this documentation but frankly, I don't understand it.
Your actual problem is that you want to configure something in your module.
Reading a configuration file does not solve that problem, it just introduces another problem.
To configure something in your module, use a module parameter:
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sefu");
static char *my_param = "default";
module_param(my_param, charp, 0444);
MODULE_PARM_DESC(my_param, "my little configuration string");
int init_module(void)
{
printk(KERN_INFO "The parameter is: %s\n", my_param);
return 0;
}
void cleanup_module(void)
{
}
To set that value, load your module with something like
modprobe mymodule my_param=whatever
or put this line into some .conf file in /etc/modprobe.d/:
options mymodule my_param=whatever
I am interested in starting a daemon inside an lxc container with its stdin/stdout as a socket passed from the host, inetd style. Is this possible?
Be advised, if using an LXC "snapshot" clone, with a directory backing store (which thus uses overlayfs), then Unix FIFO pipes are currently broken. See:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1214500
I don't think LXC has native support, but you could always just run your lxc command under xinetd to get what you want. Or write your own server that talks sockets on one side and talks LXC (via popen() or something) on the other side.
inetd is a daemon that starts (non-daemonic) programs that use stdin/stdout to listen/talk to you
The LXC utilities lxc-start and lxc-execute insist on closing all open file descriptors (including stdin/stdout) making them useless with inetd. They eventually call clone(2), however, and so can you, writing your own C wrapper like this:
#define STACKSIZE 409600
/* choose your favourite brand of isolationism below */
#define SPLENDID_ISOLATION (CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWNET)
int exec_command(void* arg) {
/* don't close stdin/stdout here! */
execl("command", "command", arg, NULL);
return 1;
}
void main(int argc, char **argv) {
void *stack = malloc(STACKSIZE) + STACKSIZE - 1; /* grows downwards */
clone(&exec_command, stack, SIGCHLD|CLONE_VFORK|SPLENDID_ISOLATION, argv[1]);
wait(NULL);
}
This wrapper can then be run under inetd.